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