##// END OF EJS Templates
change set_preset to activate_preset...
Matthias BUSSONNIER -
Show More
@@ -1,349 +1,358
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2012 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 // CellToolbar
10 10 //============================================================================
11 11
12 12
13 13 /**
14 14 * A Module to control the per-cell toolbar.
15 15 * @module IPython
16 16 * @namespace IPython
17 17 * @submodule CellToolbar
18 18 */
19 19 var IPython = (function (IPython) {
20 20 "use strict";
21 21
22 22
23 23 /**
24 24 * @constructor
25 25 * @class CellToolbar
26 26 * @param {The cell to attach the metadata UI to} cell
27 27 */
28 28 var CellToolbar = function (cell) {
29 29 CellToolbar._instances.push(this);
30 30 this.inner_element = $('<div/>');
31 31 this.cell = cell;
32 32 this.element = $('<div/>').addClass('celltoolbar')
33 33 .append(this.inner_element)
34 34 this.rebuild();
35 35 return this;
36 36 };
37 37
38 38 CellToolbar.dropdown_preset_element = $('<select/>')
39 39 .addClass('ui-widget ui-widget-content')
40 40 .attr('id', 'celltoolbar_selector')
41 41 .append($('<option/>').attr('value', '').text('None'))
42 42
43 43 CellToolbar.dropdown_preset_element.change(function(){
44 44 var val = CellToolbar.dropdown_preset_element.val()
45 45 if(val ==''){
46 46 $('body').removeClass('celltoolbar-on')
47 47 } else {
48 48 $('body').addClass('celltoolbar-on')
49 CellToolbar.set_preset(val)
49 CellToolbar.activate_preset(val)
50 50 }
51 51 })
52 52
53 53
54 54
55 55 /**
56 56 * Class variable that should contain a dict of all availlable callback
57 57 * we need to think of wether or not we allow nested namespace
58 58 * @property _callback_dict
59 59 * @private
60 * @static
61 * @type Dict
60 62 */
61 63 CellToolbar._callback_dict = {};
62 64
63 65 /**
64 66 * Class variable that should contain the reverse order list of the button
65 67 * to add to the toolbar of each cell
66 68 * @property _ui_controls_list
67 69 * @private
70 * @static
71 * @type List
68 72 */
69 73 CellToolbar._ui_controls_list = [];
70 74
71 75 /**
72 * keep a list of all instances to
73 * be able to llop over them...
74 * but how to 'destroy' them ?
75 * have to think about it...
76 * or loop over the cells, and find their CellToolbar instances.
76 * Class variable that should contains the CellToolbar instances for each
77 * cell of the notebook
78 *
77 79 * @private
78 80 * @property _instances
81 * @static
82 * @type List
79 83 */
80 84 CellToolbar._instances =[]
81 85
82 86 /**
83 87 * keep a list of all the availlabel presets for the toolbar
84 88 * @private
85 89 * @property _presets
90 * @static
91 * @type Dict
86 92 */
87 93 CellToolbar._presets ={}
88 94
89 95 // this is by design not a prototype.
90 96 /**
91 97 * Register a callback to create an UI element in a cell toolbar.
92 98 * @method register_callback
93 99 * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name
94 100 * for easier sorting and avoid collision
95 101 * @param callback {function(div, cell)} callback that will be called to generate the ui element
96 102 *
97 103 *
98 104 * The callback will receive the following element :
99 105 *
100 106 * * a div in which to add element.
101 * * the cell it is responsable from
107 * * the cell it is responsible from
102 108 *
103 109 * @example
104 110 *
105 111 * Example that create callback for a button that toggle between `true` and `false` label,
106 112 * with the metadata under the key 'foo' to reflect the status of the button.
107 113 *
108 114 * // first param reference to a DOM div
109 115 * // second param reference to the cell.
110 116 * var toggle = function(div, cell) {
111 117 * var button_container = $(div)
112 118 *
113 119 * // let's create a button that show the current value of the metadata
114 120 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
115 121 *
116 122 * // On click, change the metadata value and update the button label
117 123 * button.click(function(){
118 124 * var v = cell.metadata.foo;
119 125 * cell.metadata.foo = !v;
120 126 * button.button("option", "label", String(!v));
121 127 * })
122 128 *
123 129 * // add the button to the DOM div.
124 130 * button_container.append(button);
125 131 * }
126 132 *
127 133 * // now we register the callback under the name `foo` to give the
128 134 * // user the ability to use it later
129 135 * CellToolbar.register_callback('foo', toggle);
130 136 */
131 137 CellToolbar.register_callback = function(name, callback){
132 // what do we do if name already exist ?
138 // Overwrite if it already exists.
133 139 CellToolbar._callback_dict[name] = callback;
134 140 };
135 141
136 142 /**
137 143 * Register a preset of UI element in a cell toolbar.
138 144 * Not supported Yet.
139 145 * @method register_preset
140 146 * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name
141 147 * for easier sorting and avoid collision
142 148 * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list
143 149 * should correspond to a name of a registerd callback.
144 150 *
145 151 * @private
146 152 * @example
147 153 *
148 154 * CellToolbar.register_callback('foo.c1', function(div, cell){...});
149 155 * CellToolbar.register_callback('foo.c2', function(div, cell){...});
150 156 * CellToolbar.register_callback('foo.c3', function(div, cell){...});
151 157 * CellToolbar.register_callback('foo.c4', function(div, cell){...});
152 158 * CellToolbar.register_callback('foo.c5', function(div, cell){...});
153 159 *
154 160 * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5'])
155 161 * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5'])
156 162 */
157 163 CellToolbar.register_preset = function(name, preset_list){
158 164 CellToolbar._presets[name] = preset_list
159 165 CellToolbar.dropdown_preset_element.append(
160 166 $('<option/>').attr('value', name).text(name)
161 167 )
162 168 }
163 169 /**
164 * set an UI preset from `register_preset`
165 * @method set_preset
170 * Activate an UI preset from `register_preset`
171 *
172 * This does not update the selection UI.
173 *
174 * @method activate_preset
166 175 * @param preset_name {String} string corresponding to the preset name
167 176 *
168 177 * @static
169 178 * @private
170 179 * @example
171 180 *
172 * CellToolbar.set_preset('foo.foo_preset1');
181 * CellToolbar.activate_preset('foo.foo_preset1');
173 182 */
174 CellToolbar.set_preset= function(preset_name){
183 CellToolbar.activate_preset= function(preset_name){
175 184 var preset = CellToolbar._presets[preset_name];
176 185
177 186 if(preset != undefined){
178 187 CellToolbar._ui_controls_list = preset;
179 188 CellToolbar.rebuild_all();
180 189 }
181 190 }
182 191
183 192
184 193 // this is by design not a prototype.
185 194 /**
186 195 * This should be called on the class and not on a instance as it will trigger
187 196 * rebuild of all the instances.
188 197 * @method rebuild_all
189 198 * @static
190 199 *
191 200 */
192 201 CellToolbar.rebuild_all = function(){
193 202 for(var i in CellToolbar._instances){
194 203 CellToolbar._instances[i].rebuild();
195 204 }
196 205 }
197 206
198 207 /**
199 208 * Rebuild all the button on the toolbar to update it's state.
200 209 * @method rebuild
201 210 */
202 211 CellToolbar.prototype.rebuild = function(){
203 212 // strip evrything from the div
204 213 // which is probabli metainner.
205 214 // or this.element.
206 215 this.inner_element.empty();
207 216
208 217 var cdict = CellToolbar._callback_dict;
209 218 var preset = CellToolbar._ui_controls_list;
210 219 // Yes we iterate on the class varaible, not the instance one.
211 220 for ( var index in CellToolbar._ui_controls_list){
212 221 var local_div = $('<div/>').addClass('button_container');
213 222 // Note,
214 223 // do this the other way, wrap in try/catch and don't append if any errors.
215 224 this.inner_element.append(local_div)
216 225 cdict[preset[index]](local_div, this.cell)
217 226 }
218 227
219 228 }
220 229
221 230
222 231 /**
223 232 */
224 233 CellToolbar.utils = {};
225 234
226 235 /**
227 236 * A utility function to generate bindings between a checkbox and cell/metadata
228 237 * @method utils.checkbox_ui_generator
229 238 * @static
230 239 *
231 240 * @param name {string} Label in front of the checkbox
232 241 * @param setter {function( cell, newValue )}
233 242 * A setter method to set the newValue
234 243 * @param getter {function( cell )}
235 244 * A getter methods which return the current value.
236 245 *
237 246 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
238 247 *
239 248 * @example
240 249 *
241 250 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
242 251 *
243 252 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
244 253 * // setter
245 254 * function(cell, value){
246 255 * // we check that the slideshow namespace exist and create it if needed
247 256 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
248 257 * // set the value
249 258 * cell.metadata.slideshow.isSectionStart = value
250 259 * },
251 260 * //geter
252 261 * function(cell){ var ns = cell.metadata.slideshow;
253 262 * // if the slideshow namespace does not exist return `undefined`
254 263 * // (will be interpreted as `false` by checkbox) otherwise
255 264 * // return the value
256 265 * return (ns == undefined)? undefined: ns.isSectionStart
257 266 * }
258 267 * );
259 268 *
260 269 * CellToolbar.register_callback('newSlide', newSlide);
261 270 *
262 271 */
263 272 CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){
264 273 return function(div, cell) {
265 274 var button_container = $(div)
266 275
267 276 var chkb = $('<input/>').attr('type', 'checkbox');
268 277 var lbl = $('<label/>').append($('<span/>').text(name).css('font-size', '77%'));
269 278 lbl.append(chkb);
270 279 chkb.attr("checked", getter(cell));
271 280
272 281 chkb.click(function(){
273 282 var v = getter(cell);
274 283 setter(cell, !v);
275 284 chkb.attr("checked", !v);
276 285 })
277 286 button_container.append($('<div/>').append(lbl));
278 287
279 288 }
280 289 }
281 290
282 291 /**
283 292 * A utility function to generate bindings between a dropdown list cell
284 293 * @method utils.select_ui_generator
285 294 * @static
286 295 *
287 296 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
288 297 * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list,
289 298 * and second the corresponding value to be passed to setter/return by getter.
290 299 * @param setter {function( cell, newValue )}
291 300 * A setter method to set the newValue
292 301 * @param getter {function( cell )}
293 302 * A getter methods which return the current value of the metadata.
294 303 * @param [label=""] {String} optionnal label for the dropdown menu
295 304 *
296 305 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
297 306 *
298 307 * @example
299 308 *
300 309 * var select_type = CellToolbar.utils.select_ui_generator([
301 310 * ["<None>" , undefined ],
302 311 * ["Header Slide" , "header_slide" ],
303 312 * ["Slide" , "slide" ],
304 313 * ["Fragment" , "fragment" ],
305 314 * ["Skip" , "skip" ],
306 315 * ],
307 316 * // setter
308 317 * function(cell, value){
309 318 * // we check that the slideshow namespace exist and create it if needed
310 319 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
311 320 * // set the value
312 321 * cell.metadata.slideshow.slide_type = value
313 322 * },
314 323 * //geter
315 324 * function(cell){ var ns = cell.metadata.slideshow;
316 325 * // if the slideshow namespace does not exist return `undefined`
317 326 * // (will be interpreted as `false` by checkbox) otherwise
318 327 * // return the value
319 328 * return (ns == undefined)? undefined: ns.slide_type
320 329 * }
321 330 * CellToolbar.register_callback('slideshow.select', select_type);
322 331 *
323 332 */
324 333 CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label){
325 334 label= label? label: "";
326 335 return function(div, cell) {
327 336 var button_container = $(div)
328 337 var lbl = $("<label/>").append($('<span/>').text(label).css('font-size', '77%'));
329 338 var select = $('<select/>');
330 339 for(var itemn in list_list){
331 340 var opt = $('<option/>');
332 341 opt.attr('value', list_list[itemn][1])
333 342 opt.text(list_list[itemn][0])
334 343 select.append(opt);
335 344 }
336 345 select.val(getter(cell));
337 346 select.change(function(){
338 347 setter(cell, select.val());
339 348 });
340 349 button_container.append($('<div/>').append(lbl).append(select));
341 350
342 351 }
343 352 };
344 353
345 354
346 355 IPython.CellToolbar = CellToolbar;
347 356
348 357 return IPython;
349 358 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now