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