##// END OF EJS Templates
Grammar and spelling improvements
Ben Rousch -
Show More
@@ -1,612 +1,613 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Embrasing web standards"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 "One of the main reason that allowed us to developp the current notebook web application \n",
15 "was to embrase the web technology. \n",
14 "One of the main reasons we developed the current notebook as a web application \n",
15 "is to embrace the available-everywhere web technology. \n",
16 16 "\n",
17 "By beeing a pure web application using HTML, Javascript and CSS, the Notebook can get \n",
18 "all the web technology improvement for free. Thus, as browsers support for different \n",
19 "media extend, The notebook web app should be able to be compatible without modification. \n",
17 "Being a pure web application using only HTML, Javascript and CSS, the Notebook can access \n",
18 "all of the web technology improvements for free. Thus, as browsers support for different \n",
19 "media extend, the notebook web app should be compatible without modification. \n",
20 20 "\n",
21 "This is also true with performance of the User Interface as the speed of javascript VM increase. "
21 "This is also true with performance of the User Interface as the speed of the Javascript \n",
22 "VM increases. "
22 23 ]
23 24 },
24 25 {
25 26 "cell_type": "markdown",
26 27 "metadata": {},
27 28 "source": [
28 29 "The other advantage of using only web technology is that the code of the interface is fully accessible to the end user, and modifiable live.\n",
29 30 "Even if this task is not always easy, we strive to keep our code as accessible and reusable as possible.\n",
30 "This should allow with minimum effort to develop small extensions that customize the behavior of the web interface. "
31 "This should allow - with minimum effort - development of small extensions that customize the behavior of the web interface. "
31 32 ]
32 33 },
33 34 {
34 35 "cell_type": "markdown",
35 36 "metadata": {},
36 37 "source": [
37 "## Tempering with Notebook app"
38 "## Tampering with the Notebook app"
38 39 ]
39 40 },
40 41 {
41 42 "cell_type": "markdown",
42 43 "metadata": {},
43 44 "source": [
44 "The first tool that is availlable to you and that you shoudl be aware of are browser \"developpers tool\". The exact naming can change across browser, and might require the installation of extensions. But basically they can allow you to inspect/modify the DOM, and interact with the javascript code that run the frontend.\n",
45 "The first tool that is available to you and that you should be aware of are browser \"developer tools\". The exact name of these tools is different in each browser, and might require the installation of extensions. But basically they can allow you to inspect/modify the DOM, and interact with the Javascript code that runs the frontend.\n",
45 46 "\n",
46 " - In Chrome and safari Developper tools are in the menu [Put mmenu name in english here] \n",
47 " - In firefox you might need to install [Firebug](http://getfirebug.com/)\n",
47 " - In Chrome and Safari, Developer tools are in the menu [Menu -> More tools -> Developer Tools] \n",
48 " - In Firefox you might need to install [Firebug](http://getfirebug.com/)\n",
48 49 " - others ?\n",
49 50 " \n",
50 "Those will be your best friends to debug and try different approach for your extensions."
51 "Those will be your best friends to debug and try different approaches for your extensions."
51 52 ]
52 53 },
53 54 {
54 55 "cell_type": "markdown",
55 56 "metadata": {},
56 57 "source": [
57 58 "### Injecting JS"
58 59 ]
59 60 },
60 61 {
61 62 "cell_type": "markdown",
62 63 "metadata": {},
63 64 "source": [
64 65 "#### using magics"
65 66 ]
66 67 },
67 68 {
68 69 "cell_type": "markdown",
69 70 "metadata": {},
70 71 "source": [
71 "Above tools can be tedious to edit long javascipt files. Hopefully we provide the `%%javascript` magic. This allows you to quickly inject javascript into the notebook. Still the javascript injected this way will not survive reloading. Hence it is a good tool for testing an refinig a script.\n",
72 "The above tools can be tedious for editing long Javascipt files. Helpfully, we provide the `%%javascript` magic. This allows you to quickly inject Javascript into the notebook. Still, the Javascript injected this way will not survive reloading. Hence, it is a good tool for testing and refining a script.\n",
72 73 "\n",
73 "You might see here and there people modifying css and injecting js into notebook by reading file and publishing them into the notebook.\n",
74 "Not only this often break the flow of the notebook and make the re-execution of the notebook broken, but it also mean that you need to execute those cells on all the notebook every time you need to update the code.\n",
74 "You might see here and there people modifying CSS and injecting Javascript into notebook by reading files and publishing them into the notebook.\n",
75 "Not only does this often break the flow of the notebook and break the re-execution of the notebook, but it also means that you need to execute those cells every time you need to update the code.\n",
75 76 "\n",
76 "This can still be usefull in some cases, like the `%autosave` magic that allows to control the time between each save. But this can be replaced by a Javascript dropdown menu to select save interval."
77 "This can still be useful in some cases, like the `%autosave` magic that allows you to control the time between each save. But this can be replaced by a Javascript dropdown menu to select a save interval."
77 78 ]
78 79 },
79 80 {
80 81 "cell_type": "code",
81 82 "execution_count": null,
82 83 "metadata": {
83 84 "collapsed": false
84 85 },
85 86 "outputs": [],
86 87 "source": [
87 "## you can inspect the autosave code to see what it does.\n",
88 "## You can inspect the autosave code to see what it does.\n",
88 89 "%autosave??"
89 90 ]
90 91 },
91 92 {
92 93 "cell_type": "markdown",
93 94 "metadata": {},
94 95 "source": [
95 96 "#### custom.js"
96 97 ]
97 98 },
98 99 {
99 100 "cell_type": "markdown",
100 101 "metadata": {},
101 102 "source": [
102 "To inject Javascript we provide an entry point: `custom.js` that allow teh user to execute and load other resources into the notebook.\n",
103 "Javascript code in `custom.js` will be executed when the notebook app start and can then be used to customise almost anything in the UI and in the behavior of the notebook.\n",
103 "To inject Javascript we provide an entry point: `custom.js` that allows the user to execute and load other resources into the notebook.\n",
104 "Javascript code in `custom.js` will be executed when the notebook app starts and can then be used to customize almost anything in the UI and in the behavior of the notebook.\n",
104 105 "\n",
105 "`custom.js` can be found in IPython profile dir, and so you can have different UI modification on a per profile basis, as well as share your modfication with others."
106 "`custom.js` can be found in the IPython profile dir, and so you can have different UI modifications on a per-profile basis, as well as share your modfications with others."
106 107 ]
107 108 },
108 109 {
109 110 "cell_type": "markdown",
110 111 "metadata": {},
111 112 "source": [
112 113 "##### Because we like you...."
113 114 ]
114 115 },
115 116 {
116 117 "cell_type": "markdown",
117 118 "metadata": {},
118 119 "source": [
119 "You have been provided with an already existing profile folder with this tutorial...\n",
120 "start the notebook from the root of the tutorial directory with :\n",
120 "You have been provided with an pre-existing profile folder with this tutorial...\n",
121 "Start the notebook from the root of the tutorial directory with :\n",
121 122 "\n",
122 123 "```bash\n",
123 124 "$ ipython notebook --ProfileDir.location=./profile_euroscipy\n",
124 125 "```"
125 126 ]
126 127 },
127 128 {
128 129 "cell_type": "markdown",
129 130 "metadata": {},
130 131 "source": [
131 132 "##### but back to theory"
132 133 ]
133 134 },
134 135 {
135 136 "cell_type": "code",
136 137 "execution_count": null,
137 138 "metadata": {
138 139 "collapsed": false
139 140 },
140 141 "outputs": [],
141 142 "source": [
142 143 "profile_dir = ! ipython locate\n",
143 144 "profile_dir = profile_dir[0]\n",
144 145 "profile_dir"
145 146 ]
146 147 },
147 148 {
148 149 "cell_type": "markdown",
149 150 "metadata": {},
150 151 "source": [
151 152 "and custom js is in "
152 153 ]
153 154 },
154 155 {
155 156 "cell_type": "code",
156 157 "execution_count": null,
157 158 "metadata": {
158 159 "collapsed": false
159 160 },
160 161 "outputs": [],
161 162 "source": [
162 163 "import os.path\n",
163 164 "custom_js_path = os.path.join(profile_dir,'profile_default','static','custom','custom.js')"
164 165 ]
165 166 },
166 167 {
167 168 "cell_type": "code",
168 169 "execution_count": null,
169 170 "metadata": {
170 171 "collapsed": false
171 172 },
172 173 "outputs": [],
173 174 "source": [
174 175 "# my custom js\n",
175 176 "with open(custom_js_path) as f:\n",
176 177 " for l in f: \n",
177 178 " print l,"
178 179 ]
179 180 },
180 181 {
181 182 "cell_type": "markdown",
182 183 "metadata": {},
183 184 "source": [
184 "Note that `custom.js` is ment to be modified by user, when writing a script, you can define it in a separate file and add a line of configuration into `custom.js` that will fetch and execute the file."
185 "Note that `custom.js` is meant to be modified by the user. When writing a script, you can define it in a separate file and add a line of configuration into `custom.js` that will fetch and execute the file."
185 186 ]
186 187 },
187 188 {
188 189 "cell_type": "markdown",
189 190 "metadata": {},
190 191 "source": [
191 "**Warning** : even if modification of `custom.js` take effect immediately after browser refresh (except if browser cache is aggressive), *creating* a file in `static/` directory need a **server restart**."
192 "**Warning** : even if modification of `custom.js` takes effect immediately after a browser refresh (except if browser cache is aggressive), *creating* a file in `static/` directory needs a **server restart**."
192 193 ]
193 194 },
194 195 {
195 196 "cell_type": "markdown",
196 197 "metadata": {},
197 198 "source": [
198 199 "## Exercise :"
199 200 ]
200 201 },
201 202 {
202 203 "cell_type": "markdown",
203 204 "metadata": {},
204 205 "source": [
205 206 " - Create a `custom.js` in the right location with the following content:\n",
206 207 "```javascript\n",
207 208 "alert(\"hello world from custom.js\")\n",
208 209 "```\n",
209 210 "\n",
210 211 " - Restart your server and open any notebook.\n",
211 212 " - Be greeted by custom.js"
212 213 ]
213 214 },
214 215 {
215 216 "cell_type": "markdown",
216 217 "metadata": {},
217 218 "source": [
218 "Have a look at [default custom.js](https://github.com/ipython/ipython/blob/1.x/IPython/html/static/custom/custom.js), to see it's content and some more explanation."
219 "Have a look at [default custom.js](https://github.com/ipython/ipython/blob/1.x/IPython/html/static/custom/custom.js), to see it's contents and for more explanation."
219 220 ]
220 221 },
221 222 {
222 223 "cell_type": "markdown",
223 224 "metadata": {},
224 225 "source": [
225 226 "#### For the quick ones : "
226 227 ]
227 228 },
228 229 {
229 230 "cell_type": "markdown",
230 231 "metadata": {},
231 232 "source": [
232 "We've seen above that you can change the autosave rate by using a magic. This is typically something I don't want to type everytime, and that I don't like to embed into my workwlow and documents. (reader don't care what my autosave time is), let's build an extension that allow to do it. "
233 "We've seen above that you can change the autosave rate by using a magic. This is typically something I don't want to type everytime, and that I don't like to embed into my workflow and documents. (The reader doesn't care what my autosave time is), so let's build an extension that allow to do it. "
233 234 ]
234 235 },
235 236 {
236 237 "cell_type": "markdown",
237 238 "metadata": {
238 239 "foo": true
239 240 },
240 241 "source": [
241 "Create a dropdow elemement in the toolbar (DOM `IPython.toolbar.element`), you will need \n",
242 "Create a dropdown elemement in the toolbar (DOM `IPython.toolbar.element`). You will need \n",
242 243 "\n",
243 244 "- `IPython.notebook.set_autosave_interval(miliseconds)`\n",
244 245 "- know that 1min = 60 sec, and 1 sec = 1000 ms"
245 246 ]
246 247 },
247 248 {
248 249 "cell_type": "markdown",
249 250 "metadata": {},
250 251 "source": [
251 252 "```javascript\n",
252 253 "\n",
253 254 "var label = jQuery('<label/>').text('AutoScroll Limit:');\n",
254 255 "var select = jQuery('<select/>')\n",
255 256 " //.append(jQuery('<option/>').attr('value', '2').text('2min (default)'))\n",
256 257 " .append(jQuery('<option/>').attr('value', undefined).text('disabled'))\n",
257 258 "\n",
258 259 " // TODO:\n",
259 260 " //the_toolbar_element.append(label)\n",
260 261 " //the_toolbar_element.append(select);\n",
261 262 " \n",
262 263 "select.change(function() {\n",
263 264 " var val = jQuery(this).val() // val will be the value in [2]\n",
264 265 " // TODO\n",
265 266 " // this will be called when dropdown changes\n",
266 267 "\n",
267 268 "});\n",
268 269 "\n",
269 270 "var time_m = [1,5,10,15,30];\n",
270 271 "for (var i=0; i < time_m.length; i++) {\n",
271 272 " var ts = time_m[i];\n",
272 273 " //[2] ____ this will be `val` on [1] \n",
273 274 " // | \n",
274 275 " // v \n",
275 276 " select.append($('<option/>').attr('value', ts).text(thr+'min'));\n",
276 277 " // this will fill up the dropdown `select` with\n",
277 278 " // 1 min\n",
278 279 " // 5 min\n",
279 280 " // 10 min\n",
280 281 " // 10 min\n",
281 282 " // ...\n",
282 283 "}\n",
283 284 "```"
284 285 ]
285 286 },
286 287 {
287 288 "cell_type": "markdown",
288 289 "metadata": {},
289 290 "source": [
290 "#### A non interactive example first"
291 "#### A non-interactive example first"
291 292 ]
292 293 },
293 294 {
294 295 "cell_type": "markdown",
295 296 "metadata": {},
296 297 "source": [
297 298 "I like my cython to be nicely highlighted\n",
298 299 "\n",
299 300 "```javascript\n",
300 301 "traitlets.config.cell_magic_highlight['magic_text/x-cython'] = {}\n",
301 302 "traitlets.config.cell_magic_highlight['magic_text/x-cython'].reg = [/^%%cython/]\n",
302 303 "```\n",
303 304 "\n",
304 "`text/x-cython` is the name of CodeMirror mode name, `magic_` prefix will just patch the mode so that the first line that contains a magic does not screw up the highlighting. `reg`is a list or regular expression that will trigger the change of mode."
305 "`text/x-cython` is the name of a CodeMirror mode name, the `magic_` prefix will just patch the mode so that the first line that contains a magic does not screw up the highlighting. `reg`is a list or regular expression that will trigger the change of mode."
305 306 ]
306 307 },
307 308 {
308 309 "cell_type": "markdown",
309 310 "metadata": {},
310 311 "source": [
311 312 "#### Get more docs"
312 313 ]
313 314 },
314 315 {
315 316 "cell_type": "markdown",
316 317 "metadata": {},
317 318 "source": [
318 "Sadly you will have to read the js source file (but there are lots of comments) an/or build the javascript documentation using yuidoc.\n",
319 "Sadly, you will have to read the Javascript source file (but there are lots of comments) and/or build the Javascript documentation using YUIDoc.\n",
319 320 "If you have `node` and `yui-doc` installed:"
320 321 ]
321 322 },
322 323 {
323 324 "cell_type": "markdown",
324 325 "metadata": {},
325 326 "source": [
326 327 "```bash\n",
327 328 "$ cd ~/ipython/IPython/html/static/notebook/js/\n",
328 329 "$ yuidoc . --server\n",
329 330 "warn: (yuidoc): Failed to extract port, setting to the default :3000\n",
330 331 "info: (yuidoc): Starting YUIDoc@0.3.45 using YUI@3.9.1 with NodeJS@0.10.15\n",
331 332 "info: (yuidoc): Scanning for yuidoc.json file.\n",
332 333 "info: (yuidoc): Starting YUIDoc with the following options:\n",
333 334 "info: (yuidoc):\n",
334 335 "{ port: 3000,\n",
335 336 " nocode: false,\n",
336 337 " paths: [ '.' ],\n",
337 338 " server: true,\n",
338 339 " outdir: './out' }\n",
339 340 "info: (yuidoc): Scanning for yuidoc.json file.\n",
340 341 "info: (server): Starting server: http://127.0.0.1:3000\n",
341 342 "```\n",
342 343 "\n",
343 "and browse http://127.0.0.1:3000 to get docs"
344 "and browse to http://127.0.0.1:3000 to get the docs"
344 345 ]
345 346 },
346 347 {
347 348 "cell_type": "markdown",
348 349 "metadata": {
349 350 "foo": true
350 351 },
351 352 "source": [
352 353 "#### Some convenience methods"
353 354 ]
354 355 },
355 356 {
356 357 "cell_type": "markdown",
357 358 "metadata": {},
358 359 "source": [
359 "By browsing the doc you will see that we have soem convenience methods that avoid to re-invent the UI everytime :\n",
360 "By browsing the docs you will see that we have some convenience methods that avoid re-inventing the UI everytime :\n",
360 361 "```javascript\n",
361 362 "IPython.toolbar.add_buttons_group([\n",
362 363 " {\n",
363 364 " 'label' : 'run qtconsole',\n",
364 365 " 'icon' : 'icon-terminal', // select your icon from \n",
365 366 " // http://fortawesome.github.io/Font-Awesome/icons/\n",
366 367 " 'callback': function(){IPython.notebook.kernel.execute('%qtconsole')}\n",
367 368 " }\n",
368 369 " // add more button here if needed.\n",
369 370 " ]);\n",
370 371 "```\n",
371 372 "with a [lot of icons] you can select from. \n",
372 373 "\n",
373 374 "[lot of icons]: http://fortawesome.github.io/Font-Awesome/icons/"
374 375 ]
375 376 },
376 377 {
377 378 "cell_type": "markdown",
378 379 "metadata": {
379 380 "foo": true
380 381 },
381 382 "source": [
382 383 "## Cell Metadata"
383 384 ]
384 385 },
385 386 {
386 387 "cell_type": "markdown",
387 388 "metadata": {
388 389 "foo": true
389 390 },
390 391 "source": [
391 "The most requested feature is generaly to be able to distinguish individual cell in th enotebook, or run specific action with them.\n",
392 "To do so, you can either use `IPython.notebook.get_selected_cell()`, or rely on `CellToolbar`. This allow you to register aset of action and graphical element that will be attached on individual cells."
392 "The most requested feature is generally to be able to distinguish individual cells in the notebook, or run specific actions with them.\n",
393 "To do so, you can either use `IPython.notebook.get_selected_cell()`, or rely on `CellToolbar`. This allows you to register a set of actions and graphical elements that will be attached to individual cells."
393 394 ]
394 395 },
395 396 {
396 397 "cell_type": "markdown",
397 398 "metadata": {},
398 399 "source": [
399 400 "### Cell Toolbar"
400 401 ]
401 402 },
402 403 {
403 404 "cell_type": "markdown",
404 405 "metadata": {},
405 406 "source": [
406 "You can see some example of what can be done by toggling the `Cell Toolbar` selector in the toolbar on top of the notebook. It provide two default `presets` that are `Default` and `slideshow`. Default allow edit the metadata attached to each cell manually."
407 "You can see some examples of what can be done by toggling the `Cell Toolbar` selector in the toolbar on top of the notebook. It provides two default `presets` that are `Default` and `slideshow`. Defaults allow editing the metadata attached to each cell manually."
407 408 ]
408 409 },
409 410 {
410 411 "cell_type": "markdown",
411 412 "metadata": {},
412 413 "source": [
413 "First we define a function that takes at first parameter an element on the DOM in which to inject UI element. Second element will be the cell this element will be registerd with. Then we will need to register that function ad give it a name.\n"
414 "First we define a function that takes as the first parameter an element on the DOM into which to inject UI element. The second element will be the cell with which this element will be registerd. Then we will need to register that function and give it a name.\n"
414 415 ]
415 416 },
416 417 {
417 418 "cell_type": "markdown",
418 419 "metadata": {},
419 420 "source": [
420 421 "#### Register a callback"
421 422 ]
422 423 },
423 424 {
424 425 "cell_type": "code",
425 426 "execution_count": null,
426 427 "metadata": {
427 428 "collapsed": false
428 429 },
429 430 "outputs": [],
430 431 "source": [
431 432 "%%javascript\n",
432 433 "var CellToolbar = IPython.CellToolbar\n",
433 434 "var toggle = function(div, cell) {\n",
434 435 " var button_container = $(div)\n",
435 436 "\n",
436 " // let's create a button that show the current value of the metadata\n",
437 " // Let's create a button that shows the current value of the metadata\n",
437 438 " var button = $('<button/>').addClass('btn btn-mini').text(String(cell.metadata.foo));\n",
438 439 "\n",
439 440 " // On click, change the metadata value and update the button label\n",
440 441 " button.click(function(){\n",
441 442 " var v = cell.metadata.foo;\n",
442 443 " cell.metadata.foo = !v;\n",
443 444 " button.text(String(!v));\n",
444 445 " })\n",
445 446 "\n",
446 447 " // add the button to the DOM div.\n",
447 448 " button_container.append(button);\n",
448 449 "}\n",
449 450 "\n",
450 451 " // now we register the callback under the name foo to give the\n",
451 452 " // user the ability to use it later\n",
452 453 " CellToolbar.register_callback('tuto.foo', toggle);"
453 454 ]
454 455 },
455 456 {
456 457 "cell_type": "markdown",
457 458 "metadata": {},
458 459 "source": [
459 460 "#### Registering a preset"
460 461 ]
461 462 },
462 463 {
463 464 "cell_type": "markdown",
464 465 "metadata": {},
465 466 "source": [
466 "This function can now be part of many `preset` of the CellToolBar."
467 "This function can now be part of any `preset` of the CellToolBar."
467 468 ]
468 469 },
469 470 {
470 471 "cell_type": "code",
471 472 "execution_count": null,
472 473 "metadata": {
473 474 "collapsed": false,
474 475 "foo": true,
475 476 "slideshow": {
476 477 "slide_type": "subslide"
477 478 }
478 479 },
479 480 "outputs": [],
480 481 "source": [
481 482 "%%javascript\n",
482 483 "IPython.CellToolbar.register_preset('Tutorial 1',['tuto.foo','default.rawedit'])\n",
483 484 "IPython.CellToolbar.register_preset('Tutorial 2',['slideshow.select','tuto.foo'])"
484 485 ]
485 486 },
486 487 {
487 488 "cell_type": "markdown",
488 489 "metadata": {},
489 490 "source": [
490 491 "You should now have access to two presets :\n",
491 492 "\n",
492 493 " - Tutorial 1\n",
493 494 " - Tutorial 2\n",
494 495 " \n",
495 "And check that the buttons you defin share state when you toggle preset. \n",
496 "Check moreover that the metadata of the cell is modified when you clisk the button, and that when saved on reloaded the metadata is still availlable."
496 "And check that the buttons you defined share state when you toggle preset. \n",
497 "Also check that the metadata of the cell is modified when you click the button, and that the saved metadata is still available on reload."
497 498 ]
498 499 },
499 500 {
500 501 "cell_type": "markdown",
501 502 "metadata": {},
502 503 "source": [
503 504 "#### Exercise:"
504 505 ]
505 506 },
506 507 {
507 508 "cell_type": "markdown",
508 509 "metadata": {},
509 510 "source": [
510 511 "Try to wrap the all code in a file, put this file in `{profile}/static/custom/<a-name>.js`, and add \n",
511 512 "\n",
512 513 "```\n",
513 514 "require(['custom/<a-name>']);\n",
514 515 "```\n",
515 516 "\n",
516 517 "in `custom.js` to have this script automatically loaded in all your notebooks.\n",
517 518 "\n"
518 519 ]
519 520 },
520 521 {
521 522 "cell_type": "markdown",
522 523 "metadata": {},
523 524 "source": [
524 "`require` is provided by a [javascript library](http://requirejs.org/) that allow to express dependency. For simple extension like the previous one we directly mute the global namespace, but for more complexe extension you could pass acallback to `require([...], <callback>)` call, to allow the user to pass configuration information to your plugin.\n",
525 "`require` is provided by a [javascript library](http://requirejs.org/) that allows you to express dependency. For simple extensions like the previous one, we directly mute the global namespace, but for more complex extensions you could pass a callback to the `require([...], <callback>)` call, to allow the user to pass configuration information to your plugin.\n",
525 526 "\n",
526 527 "In Python lang, \n",
527 528 "\n",
528 529 "```javascript\n",
529 530 "require(['a/b', 'c/d'], function( e, f){\n",
530 531 " e.something()\n",
531 532 " f.something()\n",
532 533 "})\n",
533 534 "```\n",
534 535 "\n",
535 536 "could be read as\n",
536 537 "```python\n",
537 538 "import a.b as e\n",
538 539 "import c.d as f\n",
539 540 "e.something()\n",
540 541 "f.something()\n",
541 542 "```\n",
542 543 "\n",
543 544 "\n",
544 545 "See for example @damianavila [\"ZenMode\" plugin](https://github.com/ipython-contrib/IPython-notebook-extensions/blob/master/custom.example.js#L34) :\n",
545 546 "\n",
546 547 "```javascript\n",
547 548 "\n",
548 549 "// read that as\n",
549 550 "// import custom.zenmode.main as zenmode\n",
550 551 "require(['custom/zenmode/main'],function(zenmode){\n",
551 552 " zenmode.background('images/back12.jpg');\n",
552 553 "})\n",
553 554 "```\n"
554 555 ]
555 556 },
556 557 {
557 558 "cell_type": "markdown",
558 559 "metadata": {},
559 560 "source": [
560 561 "#### For the quickest"
561 562 ]
562 563 },
563 564 {
564 565 "cell_type": "markdown",
565 566 "metadata": {},
566 567 "source": [
567 568 "Try to use [the following](https://github.com/ipython/ipython/blob/1.x/IPython/html/static/notebook/js/celltoolbar.js#L367) to bind a dropdown list to `cell.metadata.difficulty.select`. \n",
568 569 "\n",
569 "It should be able to take the 4 following values :\n",
570 "It should be able to take the four following values :\n",
570 571 "\n",
571 572 " - `<None>`\n",
572 573 " - `Easy`\n",
573 574 " - `Medium`\n",
574 575 " - `Hard`\n",
575 576 " \n",
576 "We will use it to customise the output of the converted notebook depending of the tag on each cell"
577 "We will use it to customize the output of the converted notebook depending on the tag on each cell"
577 578 ]
578 579 },
579 580 {
580 581 "cell_type": "code",
581 582 "execution_count": null,
582 583 "metadata": {
583 584 "collapsed": false
584 585 },
585 586 "outputs": [],
586 587 "source": [
587 588 "%load soln/celldiff.js"
588 589 ]
589 590 }
590 591 ],
591 592 "metadata": {
592 593 "kernelspec": {
593 594 "display_name": "Python 3",
594 595 "language": "python",
595 596 "name": "python3"
596 597 },
597 598 "language_info": {
598 599 "codemirror_mode": {
599 600 "name": "ipython",
600 601 "version": 3
601 602 },
602 603 "file_extension": ".py",
603 604 "mimetype": "text/x-python",
604 605 "name": "python",
605 606 "nbconvert_exporter": "python",
606 607 "pygments_lexer": "ipython3",
607 608 "version": "3.4.3"
608 609 }
609 610 },
610 611 "nbformat": 4,
611 612 "nbformat_minor": 0
612 613 }
General Comments 0
You need to be logged in to leave comments. Login now