##// END OF EJS Templates
Initial version of textbox celltoolbar ui element
Jessica B. Hamrick -
Show More
@@ -1,419 +1,449
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 'base/js/namespace',
5 'base/js/namespace',
6 'jquery',
6 'jquery',
7 'base/js/events'
7 'base/js/events'
8 ], function(IPython, $, events) {
8 ], function(IPython, $, events) {
9 "use strict";
9 "use strict";
10
10
11 var CellToolbar = function (options) {
11 var CellToolbar = function (options) {
12 // Constructor
12 // Constructor
13 //
13 //
14 // Parameters:
14 // Parameters:
15 // options: dictionary
15 // options: dictionary
16 // Dictionary of keyword arguments.
16 // Dictionary of keyword arguments.
17 // events: $(Events) instance
17 // events: $(Events) instance
18 // cell: Cell instance
18 // cell: Cell instance
19 // notebook: Notebook instance
19 // notebook: Notebook instance
20 //
20 //
21 // TODO: This leaks, when cell are deleted
21 // TODO: This leaks, when cell are deleted
22 // There is still a reference to each celltoolbars.
22 // There is still a reference to each celltoolbars.
23 CellToolbar._instances.push(this);
23 CellToolbar._instances.push(this);
24 this.notebook = options.notebook;
24 this.notebook = options.notebook;
25 this.cell = options.cell;
25 this.cell = options.cell;
26 this.create_element();
26 this.create_element();
27 this.rebuild();
27 this.rebuild();
28 return this;
28 return this;
29 };
29 };
30
30
31
31
32 CellToolbar.prototype.create_element = function () {
32 CellToolbar.prototype.create_element = function () {
33 this.inner_element = $('<div/>').addClass('celltoolbar');
33 this.inner_element = $('<div/>').addClass('celltoolbar');
34 this.element = $('<div/>').addClass('ctb_hideshow')
34 this.element = $('<div/>').addClass('ctb_hideshow')
35 .append(this.inner_element);
35 .append(this.inner_element);
36 };
36 };
37
37
38
38
39 // The default css style for the outer celltoolbar div
39 // The default css style for the outer celltoolbar div
40 // (ctb_hideshow) is display: none.
40 // (ctb_hideshow) is display: none.
41 // To show the cell toolbar, *both* of the following conditions must be met:
41 // To show the cell toolbar, *both* of the following conditions must be met:
42 // - A parent container has class `ctb_global_show`
42 // - A parent container has class `ctb_global_show`
43 // - The celltoolbar has the class `ctb_show`
43 // - The celltoolbar has the class `ctb_show`
44 // This allows global show/hide, as well as per-cell show/hide.
44 // This allows global show/hide, as well as per-cell show/hide.
45
45
46 CellToolbar.global_hide = function () {
46 CellToolbar.global_hide = function () {
47 $('body').removeClass('ctb_global_show');
47 $('body').removeClass('ctb_global_show');
48 };
48 };
49
49
50
50
51 CellToolbar.global_show = function () {
51 CellToolbar.global_show = function () {
52 $('body').addClass('ctb_global_show');
52 $('body').addClass('ctb_global_show');
53 };
53 };
54
54
55
55
56 CellToolbar.prototype.hide = function () {
56 CellToolbar.prototype.hide = function () {
57 this.element.removeClass('ctb_show');
57 this.element.removeClass('ctb_show');
58 };
58 };
59
59
60
60
61 CellToolbar.prototype.show = function () {
61 CellToolbar.prototype.show = function () {
62 this.element.addClass('ctb_show');
62 this.element.addClass('ctb_show');
63 };
63 };
64
64
65
65
66 /**
66 /**
67 * Class variable that should contain a dict of all available callback
67 * Class variable that should contain a dict of all available callback
68 * we need to think of wether or not we allow nested namespace
68 * we need to think of wether or not we allow nested namespace
69 * @property _callback_dict
69 * @property _callback_dict
70 * @private
70 * @private
71 * @static
71 * @static
72 * @type Dict
72 * @type Dict
73 */
73 */
74 CellToolbar._callback_dict = {};
74 CellToolbar._callback_dict = {};
75
75
76
76
77 /**
77 /**
78 * Class variable that should contain the reverse order list of the button
78 * Class variable that should contain the reverse order list of the button
79 * to add to the toolbar of each cell
79 * to add to the toolbar of each cell
80 * @property _ui_controls_list
80 * @property _ui_controls_list
81 * @private
81 * @private
82 * @static
82 * @static
83 * @type List
83 * @type List
84 */
84 */
85 CellToolbar._ui_controls_list = [];
85 CellToolbar._ui_controls_list = [];
86
86
87
87
88 /**
88 /**
89 * Class variable that should contain the CellToolbar instances for each
89 * Class variable that should contain the CellToolbar instances for each
90 * cell of the notebook
90 * cell of the notebook
91 *
91 *
92 * @private
92 * @private
93 * @property _instances
93 * @property _instances
94 * @static
94 * @static
95 * @type List
95 * @type List
96 */
96 */
97 CellToolbar._instances = [];
97 CellToolbar._instances = [];
98
98
99
99
100 /**
100 /**
101 * keep a list of all the available presets for the toolbar
101 * keep a list of all the available presets for the toolbar
102 * @private
102 * @private
103 * @property _presets
103 * @property _presets
104 * @static
104 * @static
105 * @type Dict
105 * @type Dict
106 */
106 */
107 CellToolbar._presets = {};
107 CellToolbar._presets = {};
108
108
109
109
110 // this is by design not a prototype.
110 // this is by design not a prototype.
111 /**
111 /**
112 * Register a callback to create an UI element in a cell toolbar.
112 * Register a callback to create an UI element in a cell toolbar.
113 * @method register_callback
113 * @method register_callback
114 * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name
114 * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name
115 * for easier sorting and avoid collision
115 * for easier sorting and avoid collision
116 * @param callback {function(div, cell)} callback that will be called to generate the ui element
116 * @param callback {function(div, cell)} callback that will be called to generate the ui element
117 * @param [cell_types] {List of String|undefined} optional list of cell types. If present the UI element
117 * @param [cell_types] {List of String|undefined} optional list of cell types. If present the UI element
118 * will be added only to cells of types in the list.
118 * will be added only to cells of types in the list.
119 *
119 *
120 *
120 *
121 * The callback will receive the following element :
121 * The callback will receive the following element :
122 *
122 *
123 * * a div in which to add element.
123 * * a div in which to add element.
124 * * the cell it is responsible from
124 * * the cell it is responsible from
125 *
125 *
126 * @example
126 * @example
127 *
127 *
128 * Example that create callback for a button that toggle between `true` and `false` label,
128 * Example that create callback for a button that toggle between `true` and `false` label,
129 * with the metadata under the key 'foo' to reflect the status of the button.
129 * with the metadata under the key 'foo' to reflect the status of the button.
130 *
130 *
131 * // first param reference to a DOM div
131 * // first param reference to a DOM div
132 * // second param reference to the cell.
132 * // second param reference to the cell.
133 * var toggle = function(div, cell) {
133 * var toggle = function(div, cell) {
134 * var button_container = $(div)
134 * var button_container = $(div)
135 *
135 *
136 * // let's create a button that show the current value of the metadata
136 * // let's create a button that show the current value of the metadata
137 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
137 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
138 *
138 *
139 * // On click, change the metadata value and update the button label
139 * // On click, change the metadata value and update the button label
140 * button.click(function(){
140 * button.click(function(){
141 * var v = cell.metadata.foo;
141 * var v = cell.metadata.foo;
142 * cell.metadata.foo = !v;
142 * cell.metadata.foo = !v;
143 * button.button("option", "label", String(!v));
143 * button.button("option", "label", String(!v));
144 * })
144 * })
145 *
145 *
146 * // add the button to the DOM div.
146 * // add the button to the DOM div.
147 * button_container.append(button);
147 * button_container.append(button);
148 * }
148 * }
149 *
149 *
150 * // now we register the callback under the name `foo` to give the
150 * // now we register the callback under the name `foo` to give the
151 * // user the ability to use it later
151 * // user the ability to use it later
152 * CellToolbar.register_callback('foo', toggle);
152 * CellToolbar.register_callback('foo', toggle);
153 */
153 */
154 CellToolbar.register_callback = function(name, callback, cell_types) {
154 CellToolbar.register_callback = function(name, callback, cell_types) {
155 // Overwrite if it already exists.
155 // Overwrite if it already exists.
156 CellToolbar._callback_dict[name] = cell_types ? {callback: callback, cell_types: cell_types} : callback;
156 CellToolbar._callback_dict[name] = cell_types ? {callback: callback, cell_types: cell_types} : callback;
157 };
157 };
158
158
159
159
160 /**
160 /**
161 * Register a preset of UI element in a cell toolbar.
161 * Register a preset of UI element in a cell toolbar.
162 * Not supported Yet.
162 * Not supported Yet.
163 * @method register_preset
163 * @method register_preset
164 * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name
164 * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name
165 * for easier sorting and avoid collision
165 * for easier sorting and avoid collision
166 * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list
166 * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list
167 * should correspond to a name of a registerd callback.
167 * should correspond to a name of a registerd callback.
168 *
168 *
169 * @private
169 * @private
170 * @example
170 * @example
171 *
171 *
172 * CellToolbar.register_callback('foo.c1', function(div, cell){...});
172 * CellToolbar.register_callback('foo.c1', function(div, cell){...});
173 * CellToolbar.register_callback('foo.c2', function(div, cell){...});
173 * CellToolbar.register_callback('foo.c2', function(div, cell){...});
174 * CellToolbar.register_callback('foo.c3', function(div, cell){...});
174 * CellToolbar.register_callback('foo.c3', function(div, cell){...});
175 * CellToolbar.register_callback('foo.c4', function(div, cell){...});
175 * CellToolbar.register_callback('foo.c4', function(div, cell){...});
176 * CellToolbar.register_callback('foo.c5', function(div, cell){...});
176 * CellToolbar.register_callback('foo.c5', function(div, cell){...});
177 *
177 *
178 * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5'])
178 * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5'])
179 * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5'])
179 * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5'])
180 */
180 */
181 CellToolbar.register_preset = function(name, preset_list, notebook) {
181 CellToolbar.register_preset = function(name, preset_list, notebook) {
182 CellToolbar._presets[name] = preset_list;
182 CellToolbar._presets[name] = preset_list;
183 events.trigger('preset_added.CellToolbar', {name: name});
183 events.trigger('preset_added.CellToolbar', {name: name});
184 // When "register_callback" is called by a custom extension, it may be executed after notebook is loaded.
184 // When "register_callback" is called by a custom extension, it may be executed after notebook is loaded.
185 // In that case, activate the preset if needed.
185 // In that case, activate the preset if needed.
186 if (notebook && notebook.metadata && notebook.metadata.celltoolbar === name){
186 if (notebook && notebook.metadata && notebook.metadata.celltoolbar === name){
187 CellToolbar.activate_preset(name);
187 CellToolbar.activate_preset(name);
188 }
188 }
189 };
189 };
190
190
191
191
192 /**
192 /**
193 * List the names of the presets that are currently registered.
193 * List the names of the presets that are currently registered.
194 *
194 *
195 * @method list_presets
195 * @method list_presets
196 * @static
196 * @static
197 */
197 */
198 CellToolbar.list_presets = function() {
198 CellToolbar.list_presets = function() {
199 var keys = [];
199 var keys = [];
200 for (var k in CellToolbar._presets) {
200 for (var k in CellToolbar._presets) {
201 keys.push(k);
201 keys.push(k);
202 }
202 }
203 return keys;
203 return keys;
204 };
204 };
205
205
206
206
207 /**
207 /**
208 * Activate an UI preset from `register_preset`
208 * Activate an UI preset from `register_preset`
209 *
209 *
210 * This does not update the selection UI.
210 * This does not update the selection UI.
211 *
211 *
212 * @method activate_preset
212 * @method activate_preset
213 * @param preset_name {String} string corresponding to the preset name
213 * @param preset_name {String} string corresponding to the preset name
214 *
214 *
215 * @static
215 * @static
216 * @private
216 * @private
217 * @example
217 * @example
218 *
218 *
219 * CellToolbar.activate_preset('foo.foo_preset1');
219 * CellToolbar.activate_preset('foo.foo_preset1');
220 */
220 */
221 CellToolbar.activate_preset = function(preset_name){
221 CellToolbar.activate_preset = function(preset_name){
222 var preset = CellToolbar._presets[preset_name];
222 var preset = CellToolbar._presets[preset_name];
223
223
224 if(preset !== undefined){
224 if(preset !== undefined){
225 CellToolbar._ui_controls_list = preset;
225 CellToolbar._ui_controls_list = preset;
226 CellToolbar.rebuild_all();
226 CellToolbar.rebuild_all();
227 }
227 }
228
228
229 events.trigger('preset_activated.CellToolbar', {name: preset_name});
229 events.trigger('preset_activated.CellToolbar', {name: preset_name});
230 };
230 };
231
231
232
232
233 /**
233 /**
234 * This should be called on the class and not on a instance as it will trigger
234 * This should be called on the class and not on a instance as it will trigger
235 * rebuild of all the instances.
235 * rebuild of all the instances.
236 * @method rebuild_all
236 * @method rebuild_all
237 * @static
237 * @static
238 *
238 *
239 */
239 */
240 CellToolbar.rebuild_all = function(){
240 CellToolbar.rebuild_all = function(){
241 for(var i=0; i < CellToolbar._instances.length; i++){
241 for(var i=0; i < CellToolbar._instances.length; i++){
242 CellToolbar._instances[i].rebuild();
242 CellToolbar._instances[i].rebuild();
243 }
243 }
244 };
244 };
245
245
246 /**
246 /**
247 * Rebuild all the button on the toolbar to update its state.
247 * Rebuild all the button on the toolbar to update its state.
248 * @method rebuild
248 * @method rebuild
249 */
249 */
250 CellToolbar.prototype.rebuild = function(){
250 CellToolbar.prototype.rebuild = function(){
251 // strip evrything from the div
251 // strip evrything from the div
252 // which is probably inner_element
252 // which is probably inner_element
253 // or this.element.
253 // or this.element.
254 this.inner_element.empty();
254 this.inner_element.empty();
255 this.ui_controls_list = [];
255 this.ui_controls_list = [];
256
256
257 var callbacks = CellToolbar._callback_dict;
257 var callbacks = CellToolbar._callback_dict;
258 var preset = CellToolbar._ui_controls_list;
258 var preset = CellToolbar._ui_controls_list;
259 // Yes we iterate on the class variable, not the instance one.
259 // Yes we iterate on the class variable, not the instance one.
260 for (var i=0; i < preset.length; i++) {
260 for (var i=0; i < preset.length; i++) {
261 var key = preset[i];
261 var key = preset[i];
262 var callback = callbacks[key];
262 var callback = callbacks[key];
263 if (!callback) continue;
263 if (!callback) continue;
264
264
265 if (typeof callback === 'object') {
265 if (typeof callback === 'object') {
266 if (callback.cell_types.indexOf(this.cell.cell_type) === -1) continue;
266 if (callback.cell_types.indexOf(this.cell.cell_type) === -1) continue;
267 callback = callback.callback;
267 callback = callback.callback;
268 }
268 }
269
269
270 var local_div = $('<div/>').addClass('button_container');
270 var local_div = $('<div/>').addClass('button_container');
271 try {
271 try {
272 callback(local_div, this.cell, this);
272 callback(local_div, this.cell, this);
273 this.ui_controls_list.push(key);
273 this.ui_controls_list.push(key);
274 } catch (e) {
274 } catch (e) {
275 console.log("Error in cell toolbar callback " + key, e);
275 console.log("Error in cell toolbar callback " + key, e);
276 continue;
276 continue;
277 }
277 }
278 // only append if callback succeeded.
278 // only append if callback succeeded.
279 this.inner_element.append(local_div);
279 this.inner_element.append(local_div);
280 }
280 }
281
281
282 // If there are no controls or the cell is a rendered TextCell hide the toolbar.
282 // If there are no controls or the cell is a rendered TextCell hide the toolbar.
283 if (!this.ui_controls_list.length) {
283 if (!this.ui_controls_list.length) {
284 this.hide();
284 this.hide();
285 } else {
285 } else {
286 this.show();
286 this.show();
287 }
287 }
288 };
288 };
289
289
290
290
291 /**
291 /**
292 */
292 */
293 CellToolbar.utils = {};
293 CellToolbar.utils = {};
294
294
295
295
296 /**
296 /**
297 * A utility function to generate bindings between a checkbox and cell/metadata
297 * A utility function to generate bindings between a checkbox and cell/metadata
298 * @method utils.checkbox_ui_generator
298 * @method utils.checkbox_ui_generator
299 * @static
299 * @static
300 *
300 *
301 * @param name {string} Label in front of the checkbox
301 * @param name {string} Label in front of the checkbox
302 * @param setter {function( cell, newValue )}
302 * @param setter {function( cell, newValue )}
303 * A setter method to set the newValue
303 * A setter method to set the newValue
304 * @param getter {function( cell )}
304 * @param getter {function( cell )}
305 * A getter methods which return the current value.
305 * A getter methods which return the current value.
306 *
306 *
307 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
307 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
308 *
308 *
309 * @example
309 * @example
310 *
310 *
311 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
311 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
312 *
312 *
313 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
313 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
314 * // setter
314 * // setter
315 * function(cell, value){
315 * function(cell, value){
316 * // we check that the slideshow namespace exist and create it if needed
316 * // we check that the slideshow namespace exist and create it if needed
317 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
317 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
318 * // set the value
318 * // set the value
319 * cell.metadata.slideshow.isSectionStart = value
319 * cell.metadata.slideshow.isSectionStart = value
320 * },
320 * },
321 * //geter
321 * //geter
322 * function(cell){ var ns = cell.metadata.slideshow;
322 * function(cell){ var ns = cell.metadata.slideshow;
323 * // if the slideshow namespace does not exist return `undefined`
323 * // if the slideshow namespace does not exist return `undefined`
324 * // (will be interpreted as `false` by checkbox) otherwise
324 * // (will be interpreted as `false` by checkbox) otherwise
325 * // return the value
325 * // return the value
326 * return (ns == undefined)? undefined: ns.isSectionStart
326 * return (ns == undefined)? undefined: ns.isSectionStart
327 * }
327 * }
328 * );
328 * );
329 *
329 *
330 * CellToolbar.register_callback('newSlide', newSlide);
330 * CellToolbar.register_callback('newSlide', newSlide);
331 *
331 *
332 */
332 */
333 CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){
333 CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){
334 return function(div, cell, celltoolbar) {
334 return function(div, cell, celltoolbar) {
335 var button_container = $(div);
335 var button_container = $(div);
336
336
337 var chkb = $('<input/>').attr('type', 'checkbox');
337 var chkb = $('<input/>').attr('type', 'checkbox');
338 var lbl = $('<label/>').append($('<span/>').text(name));
338 var lbl = $('<label/>').append($('<span/>').text(name));
339 lbl.append(chkb);
339 lbl.append(chkb);
340 chkb.attr("checked", getter(cell));
340 chkb.attr("checked", getter(cell));
341
341
342 chkb.click(function(){
342 chkb.click(function(){
343 var v = getter(cell);
343 var v = getter(cell);
344 setter(cell, !v);
344 setter(cell, !v);
345 chkb.attr("checked", !v);
345 chkb.attr("checked", !v);
346 });
346 });
347 button_container.append($('<span/>').append(lbl));
347 button_container.append($('<span/>').append(lbl));
348 };
348 };
349 };
349 };
350
350
351
351
352 /**
352 /**
353 * A utility function to generate bindings between a input field and cell/metadata
354 * @method utils.input_ui_generator
355 * @static
356 *
357 * @param name {string} Label in front of the input field
358 * @param setter {function( cell, newValue )}
359 * A setter method to set the newValue
360 * @param getter {function( cell )}
361 * A getter methods which return the current value.
362 *
363 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
364 *
365 */
366 CellToolbar.utils.input_ui_generator = function(name, setter, getter){
367 return function(div, cell, celltoolbar) {
368 var button_container = $(div);
369
370 var chkb = $('<input/>').attr('type', 'text');
371 var lbl = $('<label/>').append($('<span/>').text(name));
372 lbl.append(chkb);
373 chkb.attr("value", getter(cell));
374
375 chkb.keyup(function(){
376 setter(cell, chkb.val());
377 });
378 button_container.append($('<span/>').append(lbl));
379 };
380 };
381
382 /**
353 * A utility function to generate bindings between a dropdown list cell
383 * A utility function to generate bindings between a dropdown list cell
354 * @method utils.select_ui_generator
384 * @method utils.select_ui_generator
355 * @static
385 * @static
356 *
386 *
357 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
387 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
358 * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list,
388 * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list,
359 * and second the corresponding value to be passed to setter/return by getter. the corresponding value
389 * and second the corresponding value to be passed to setter/return by getter. the corresponding value
360 * should not be "undefined" or behavior can be unexpected.
390 * should not be "undefined" or behavior can be unexpected.
361 * @param setter {function( cell, newValue )}
391 * @param setter {function( cell, newValue )}
362 * A setter method to set the newValue
392 * A setter method to set the newValue
363 * @param getter {function( cell )}
393 * @param getter {function( cell )}
364 * A getter methods which return the current value of the metadata.
394 * A getter methods which return the current value of the metadata.
365 * @param [label=""] {String} optionnal label for the dropdown menu
395 * @param [label=""] {String} optionnal label for the dropdown menu
366 *
396 *
367 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
397 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
368 *
398 *
369 * @example
399 * @example
370 *
400 *
371 * var select_type = CellToolbar.utils.select_ui_generator([
401 * var select_type = CellToolbar.utils.select_ui_generator([
372 * ["<None>" , "None" ],
402 * ["<None>" , "None" ],
373 * ["Header Slide" , "header_slide" ],
403 * ["Header Slide" , "header_slide" ],
374 * ["Slide" , "slide" ],
404 * ["Slide" , "slide" ],
375 * ["Fragment" , "fragment" ],
405 * ["Fragment" , "fragment" ],
376 * ["Skip" , "skip" ],
406 * ["Skip" , "skip" ],
377 * ],
407 * ],
378 * // setter
408 * // setter
379 * function(cell, value){
409 * function(cell, value){
380 * // we check that the slideshow namespace exist and create it if needed
410 * // we check that the slideshow namespace exist and create it if needed
381 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
411 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
382 * // set the value
412 * // set the value
383 * cell.metadata.slideshow.slide_type = value
413 * cell.metadata.slideshow.slide_type = value
384 * },
414 * },
385 * //geter
415 * //geter
386 * function(cell){ var ns = cell.metadata.slideshow;
416 * function(cell){ var ns = cell.metadata.slideshow;
387 * // if the slideshow namespace does not exist return `undefined`
417 * // if the slideshow namespace does not exist return `undefined`
388 * // (will be interpreted as `false` by checkbox) otherwise
418 * // (will be interpreted as `false` by checkbox) otherwise
389 * // return the value
419 * // return the value
390 * return (ns == undefined)? undefined: ns.slide_type
420 * return (ns == undefined)? undefined: ns.slide_type
391 * }
421 * }
392 * CellToolbar.register_callback('slideshow.select', select_type);
422 * CellToolbar.register_callback('slideshow.select', select_type);
393 *
423 *
394 */
424 */
395 CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label) {
425 CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label) {
396 label = label || "";
426 label = label || "";
397 return function(div, cell, celltoolbar) {
427 return function(div, cell, celltoolbar) {
398 var button_container = $(div);
428 var button_container = $(div);
399 var lbl = $("<label/>").append($('<span/>').text(label));
429 var lbl = $("<label/>").append($('<span/>').text(label));
400 var select = $('<select/>');
430 var select = $('<select/>');
401 for(var i=0; i < list_list.length; i++){
431 for(var i=0; i < list_list.length; i++){
402 var opt = $('<option/>')
432 var opt = $('<option/>')
403 .attr('value', list_list[i][1])
433 .attr('value', list_list[i][1])
404 .text(list_list[i][0]);
434 .text(list_list[i][0]);
405 select.append(opt);
435 select.append(opt);
406 }
436 }
407 select.val(getter(cell));
437 select.val(getter(cell));
408 select.change(function(){
438 select.change(function(){
409 setter(cell, select.val());
439 setter(cell, select.val());
410 });
440 });
411 button_container.append($('<span/>').append(lbl).append(select));
441 button_container.append($('<span/>').append(lbl).append(select));
412 };
442 };
413 };
443 };
414
444
415 // Backwards compatability.
445 // Backwards compatability.
416 IPython.CellToolbar = CellToolbar;
446 IPython.CellToolbar = CellToolbar;
417
447
418 return {'CellToolbar': CellToolbar};
448 return {'CellToolbar': CellToolbar};
419 });
449 });
General Comments 0
You need to be logged in to leave comments. Login now