##// END OF EJS Templates
Fixing infinite recursion.
Brian E. Granger -
Show More
@@ -1,230 +1,231
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2013 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // WidgetModel, WidgetView, and WidgetManager
10 10 //============================================================================
11 11 /**
12 12 * Base Widget classes
13 13 * @module IPython
14 14 * @namespace IPython
15 15 * @submodule widget
16 16 */
17 17
18 18
19 19 // require(['components/underscore/underscore-min.js',
20 20 // 'components/backbone/backbone-min.js'],
21 21
22 22 var IPython = (function (IPython) {
23 23 "use strict";
24 24
25 25 //-----------------------------------------------------------------------
26 26 // WidgetModel class
27 27 //-----------------------------------------------------------------------
28 28 var WidgetModel = Backbone.Model.extend({});
29 29
30 30
31 31 //-----------------------------------------------------------------------
32 32 // WidgetView class
33 33 //-----------------------------------------------------------------------
34 34 var WidgetView = Backbone.View.extend({
35 35
36 36 initialize: function() {
37 37 this.model.on('change',this.refresh,this);
38 38 },
39 39
40 40 refresh: function() {
41 41 this.update();
42 42
43 43 if (this.model.css != undefined) {
44 44 for (var selector in this.model.css) {
45 45 if (this.model.css.hasOwnProperty(selector)) {
46 46
47 47 // Get the elements via the css selector. If the selector is
48 48 // blank, assume the current element is the target.
49 49 var elements = this.$el.find(selector);
50 50 if (selector=='') {
51 51 elements = this.$el;
52 52 }
53 53
54 54 // Apply the css traits to all elements that match the selector.
55 55 if (elements.length>0){
56 56 var css_traits = this.model.css[selector];
57 57 for (var css_key in css_traits) {
58 58 if (css_traits.hasOwnProperty(css_key)) {
59 59 elements.css(css_key, css_traits[css_key]);
60 60 }
61 61 }
62 62 }
63 63 }
64 64 }
65 65 }
66 66 },
67 67 });
68 68
69 69
70 70 //-----------------------------------------------------------------------
71 71 // WidgetManager class
72 72 //-----------------------------------------------------------------------
73 73 // Public constructor
74 74 var WidgetManager = function(comm_manager){
75 75 this.comm_manager = comm_manager;
76 76 this.widget_model_types = {};
77 77 this.widget_view_types = {};
78 78 this.model_widget_views = {};
79 79
80 80 var that = this;
81 81 Backbone.sync = function(method, model, options, error) {
82 82 var result = that.send_sync(method, model);
83 83 if (options.success) {
84 84 options.success(result);
85 85 }
86 86 };
87 87 }
88 88
89 89 // Register a widget model type.
90 90 WidgetManager.prototype.register_widget_model = function (widget_model_name, widget_model_type) {
91 91
92 92 // Register the widget with the comm manager. Make sure to pass this object's context
93 93 // in so `this` works in the call back.
94 94 this.comm_manager.register_target(widget_model_name, $.proxy(this.handle_com_open, this));
95 95
96 96 // Register the types of the model and view correspong to this widget type. Later
97 97 // the widget manager will initialize these when the comm is opened.
98 98 this.widget_model_types[widget_model_name] = widget_model_type;
99 99 }
100 100
101 101 // Register a widget view type.
102 102 WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
103 103 this.widget_view_types[widget_view_name] = widget_view_type;
104 104 }
105 105
106 106 // Handle when a comm is opened.
107 107 WidgetManager.prototype.handle_com_open = function (comm, msg) {
108 108 var widget_type_name = msg.content.target_name;
109 109
110 110 // Create the corresponding widget model.
111 111 var widget_model = new this.widget_model_types[widget_type_name];
112 112
113 113 // Remember comm associated with the model.
114 114 widget_model.comm = comm;
115 115 comm.model = widget_model;
116 116
117 117 // Create an array to remember the views associated with the model.
118 118 widget_model.views = [];
119 119
120 120 // Add a handle to delete the control when the comm is closed.
121 121 var that = this;
122 122 var handle_close = function(msg) {
123 123 that.handle_comm_closed(comm, msg);
124 124 }
125 125 comm.on_close(handle_close);
126 126
127 127 // Handle incomming messages.
128 128 var handle_msg = function(msg) {
129 129 that.handle_comm_msg(comm, msg);
130 130 }
131 131 comm.on_msg(handle_msg);
132 132 }
133 133
134 134 // Create view that represents the model.
135 135 WidgetManager.prototype.show_view = function (widget_area, widget_model, widget_view_name) {
136 136 var widget_view = new this.widget_view_types[widget_view_name]({model: widget_model});
137 137 widget_view.render();
138 138 widget_model.views.push(widget_view);
139 139
140 140 // Add the view's element to cell's widget div.
141 141 widget_area
142 142 .append($("<div />").append(widget_view.$el));
143 143
144 144 // Update the view based on the model contents.
145 145 widget_view.refresh();
146 146 }
147 147
148 148 // Handle incomming comm msg.
149 149 WidgetManager.prototype.handle_comm_msg = function (comm, msg) {
150 150 // Different logic for different methods.
151 151 var method = msg.content.data.method;
152 152 switch (method){
153 153 case 'show':
154 154
155 155 // TODO: Get cell from registered output handler.
156 156 var cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);
157 157 var widget_subarea = cell.element.find('.widget_area').find('.widget_subarea');
158 158
159 159 if (msg.content.data.parent != undefined) {
160 160 var find_results = widget_subarea.find("." + msg.content.data.parent);
161 161 if (find_results.length > 0) {
162 162 widget_subarea = find_results;
163 163 }
164 164 }
165 165
166 166 this.show_view(widget_subarea, comm.model, msg.content.data.view_name);
167 167 break;
168 168 case 'update':
169 169 this.handle_update(comm, msg.content.data.state);
170 170 break;
171 171 }
172 172 }
173 173
174 174 // Handle when a widget is updated via the python side.
175 175 WidgetManager.prototype.handle_update = function (comm, state) {
176 176 for (var key in state) {
177 177 if (state.hasOwnProperty(key)) {
178 178 if (key=="_css"){
179 179 comm.model.css = state[key];
180 180 } else {
181 181 comm.model.set(key, state[key]);
182 182 }
183 183 }
184 184 }
185 185 comm.model.save();
186 186 }
187 187
188 188 // Handle when a widget is closed.
189 189 WidgetManager.prototype.handle_comm_closed = function (comm, msg) {
190 190 for (var view_index in comm.model.views) {
191 191 var view = comm.model.views[view_index];
192 192 view.remove();
193 193 }
194 194 }
195 195
196 196 // Get the cell output area corresponding to the comm.
197 197 WidgetManager.prototype._get_comm_outputarea = function (comm) {
198 198 // TODO: get element from comm instead of guessing
199 199 var cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index())
200 200 return cell.output_area;
201 201 }
202 202
203 203 // Send widget state to python backend.
204 204 WidgetManager.prototype.send_sync = function (method, model) {
205 205
206 206 // Create a callback for the output if the widget has an output area associate with it.
207 207 var callbacks = {};
208 208 var comm = model.comm;
209 209 var outputarea = this._get_comm_outputarea(comm);
210 210 if (outputarea != null) {
211 211 callbacks = {
212 212 iopub : {
213 213 output : $.proxy(outputarea.handle_output, outputarea),
214 214 clear_output : $.proxy(outputarea.handle_clear_output, outputarea)}
215 215 };
216 216 };
217 217
218 var data = {sync_method: method, sync_data: model.toJSON()};
218 var model_json = model.toJSON();
219 var data = {sync_method: method, sync_data: model_json};
219 220 comm.send(data, callbacks);
220 return data;
221 return model_json;
221 222 }
222 223
223 224 IPython.WidgetManager = WidgetManager;
224 225 IPython.WidgetModel = WidgetModel;
225 226 IPython.WidgetView = WidgetView;
226 227
227 228
228 229 return IPython;
229 230
230 231 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now