Merge pull request #273 from juhasch/feature/reorg

[WIP] Restructure repository
This commit is contained in:
Juergen Hasch
2015-09-05 21:14:16 +02:00
255 changed files with 1172 additions and 707 deletions
+16 -2
View File
@@ -1,2 +1,16 @@
custom.js
custom.css
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Sphinx documentation
docs/_build/
.idea
+1 -1
View File
@@ -5,7 +5,7 @@
IPython-contrib is licensed under the terms of the Modified BSD License (also
known as New or Revised or 3-Clause BSD), as follows:
- Copyright (c) 2013-2014, IPython-contrib Developers
- Copyright (c) 2013-2015, IPython-contrib Developers
All rights reserved.
+17 -15
View File
@@ -1,9 +1,10 @@
Jupyter notebook extensions master branch
Jupyter notebook extensions
===========================
This repository contains a collection of extensions that add functionality to the Jupyter notebook.
These extensions are mostly written in Javascript and will be loaded locally in your Browser.
The IPython-contrib repository is maintained independently by a group of users and developers and not officially related to the IPython development team.
The IPython-contrib repository is maintained independently by a group of users and developers and not officially related
to the IPython development team.
The maturity of the provided extensions may vary, please create an issue if you encounter any problems.
@@ -20,19 +21,20 @@ IPython/Jupyter version support
There are different branches of the notebook extensions in this repository.
Please make sure you use the branch corresponding to your IPython/Jupyter version.
Overview
===========================
The repository is organized in different categories:
| Name | Description |
|------------|-------------|
| [usability](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki#usability) | Additional functionality for the notebook |
| [publishing](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki#publishing) | Getting your notebooks out in the wild |
| [styling](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki#styling) | Styling schemes for different looks of the notebook |
| [slidemode](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki#slidemode) | Slideshow creation |
| [testing](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki#testing) | Extensions in a early stage |
Documentation
=============
The extensions are documented in the Wiki. Please take a look [here](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki)
Some extensions are not documented. We encourage you to add documentation for them.
All extensions that are maintained and active have a markdown readme file for documentation and a yaml file to
allow them being configured using the 'nbextensions' server extension.
Installation
============
The simple case: You want to install the extensions as local user. Then, simply run `setup.py install` or install
the conda package. The conda package can also be built by running `conda build IPython-notebook-extensions`,
and then doing a `conda install nbextensions`.
For more complex installation scenarios, please look up the documentation for installing notebook extensions,
server extensions, pre/postprocessors, and templates at the Jupyter homepage http://www.jupyter.org
+2
View File
@@ -0,0 +1,2 @@
"%PYTHON%" setup.py install
if errorlevel 1 exit 1
+1
View File
@@ -0,0 +1 @@
python setup.py install
-18
View File
@@ -1,18 +0,0 @@
# Configuration file for ipython-notebook.
from IPython.utils.path import get_ipython_dir
import os
import sys
ipythondir = get_ipython_dir()
extensions = os.path.join(ipythondir,'extensions')
sys.path.append( extensions )
c = get_config()
c.NotebookApp.open_browser = False
#c.IPKernelApp.ip = '127.0.0.1'
#c.FileNotebookManager.notebook_dir = 'i:\\notebook'
c.NotebookApp.server_extensions = [ 'nbextensions' ]
c.NotebookApp.extra_template_paths = [os.path.join(ipythondir,'templates') ]
-58
View File
@@ -1,58 +0,0 @@
// Example for custom.js
// we want strict javascript that fails on ambiguous syntax
"use strict";
// activate extensions only after Notebook is initialized
require(["base/js/events"], function (events) {
events.on("app_initialized.NotebookApp", function () {
/*
* all exentensions from IPython-notebook-extensions, uncomment to activate
*/
// PUBLISHING
// IPython.load_extensions('publishing/nbviewer_theme/main')
// IPython.load_extensions('publishing/gist_it')
// IPython.load_extensions('publishing/nbconvert_button')
// IPython.load_extensions('publishing/printview/main')
// IPython.load_extensions('publishing/printviewmenu_button')
// SLIDEMODE
// IPython.load_extensions('slidemode/main')
// STYLING
// IPython.load_extensions('styling/css_selector/main')
// TESTING
// IPython.load_extensions('testing/hierarchical_collapse/main')
// USABILITY
// IPython.load_extensions('usability/aspell/ipy-aspell')
// IPython.load_extensions('usability/codefolding/main')
// IPython.load_extensions('usability/dragdrop/drag-and-drop')
// IPython.load_extensions('usability/runtools/main')
// IPython.load_extensions('usability/chrome_clipboard/main')
// IPython.load_extensions('usability/navigation-hotkeys/main')
// IPython.load_extensions('usability/toggle_all_line_number')
// IPython.load_extensions('usability/help_panel/help_panel')
// IPython.load_extensions('usability/hide_input/main')
// IPython.load_extensions('usability/split-combine')
// IPython.load_extensions('usability/read-only')
// IPython.load_extensions('usability/init_cell/main')
// IPython.load_extensions('usability/limit_output/main')
// IPython.load_extensions('usability/autosavetime')
// IPython.load_extensions('usability/autoscroll')
// IPython.load_extensions('usability/breakpoints')
// IPython.load_extensions('usability/clean_start')
// IPython.load_extensions('usability/comment-uncomment')
// IPython.load_extensions('usability/linenumbers')
// IPython.load_extensions('usability/no_exec_dunder')
// IPython.load_extensions('usability/noscroll')
// IPython.load_extensions('usability/hide_io_selected')
// IPython.load_extensions('usability/execute_time/ExecuteTime')
// IPython.load_extensions('usability/python-markdown/main')
});
});
@@ -15,7 +15,7 @@ import json
jupyterdir = jupyter_data_dir()
nbextension_dirs = (get_nbext_dir(), os.path.join(jupyterdir, 'nbextensions'))
exclude = [ 'mathjax' ]
exclude = ['mathjax']
class NBExtensionHandler(IPythonHandler):
@@ -83,8 +83,8 @@ class NBExtensionHandler(IPythonHandler):
extension_list_json = json.dumps(extension_list)
self.write(self.render_template(
'nbextensions.html',
base_url = self.base_url,
extension_list = extension_list_json,
base_url=self.base_url,
extension_list=extension_list_json,
page_title="Notebook Extension Configuration"
))
@@ -94,9 +94,9 @@ class RenderExtensionHandler(IPythonHandler):
@web.authenticated
def get(self, path):
self.write(self.render_template('rendermd.html',
base_url = self.base_url,
render_url = path,
page_title = path,
base_url=self.base_url,
render_url=path,
page_title=path,
)
)
+49
View File
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
"""PostProcessor for embedding markdown images in HTML files."""
from __future__ import print_function
import os
import re
import base64
import requests
from traitlets import Bool, Unicode, Int
from nbconvert.postprocessors.base import PostProcessorBase
class EmbedPostProcessor(PostProcessorBase):
""" Post processor designed to embed images in markdown cells as base64 encoded blob in HTML file """
def replfunc(self, match):
""" replace source url or file link with base64 encoded blob """
url = match.group(1)
imgformat = url.split('.')[-1]
if url.startswith('http'):
data = request.get(url)
elif url.startswith('data'):
img = '<img src="' + url + '" '+ match.group(2) + ' />'
return img
else:
with open(url, 'rb') as f:
data = f.read()
self.log.info("embedding url: %s, format: %s" % (url, imgformat))
b64_data=base64.b64encode(data).decode("utf-8")
if imgformat == "svg":
img = '<img src="data:image/svg+xml;base64,' + b64_data + '" ' + match.group(2) + '/>'
elif imgformat == "pdf":
img = '<img src="data:application/pdf;base64,' + b64_data + '" ' + match.group(2) + '/>'
else:
img = '<img src="data:image/'+imgformat+';base64,' + b64_data + '" '+ match.group(2) + ' />'
return img
def postprocess(self, input):
if self.config.export_format == "html":
regex = re.compile('<img\s+src="(\S+)"\s*(\S*)\s*/>')
ext = input.split('.')[-1]
output=input[0:-(len(ext)+1)] + '-embedded.' + ext
with open(input) as fin, open(output,'w') as fout:
for line in fin:
fout.write(regex.sub(self.replfunc,line))
fin.close()
fout.close()
+9
View File
@@ -0,0 +1,9 @@
from jupyter_core.paths import jupyter_config_dir, jupyter_data_dir
import os
import sys
sys.path.append(os.path.join(jupyter_data_dir(), 'extensions'))
c = get_config()
c.Exporter.template_path = [os.path.join(jupyter_data_dir(), 'templates') ]
+9
View File
@@ -0,0 +1,9 @@
from jupyter_core.paths import jupyter_config_dir, jupyter_data_dir
import os
import sys
sys.path.append(os.path.join(jupyter_data_dir(), 'extensions'))
c = get_config()
c.NotebookApp.extra_template_paths = [os.path.join(jupyter_data_dir(),'templates') ]
+38
View File
@@ -0,0 +1,38 @@
package:
name: nbextensions
version: "master"
source:
git_url: https://github.com/ipython-contrib/IPython-notebook-extensions
git_tag: master
build:
script: python setup.py install
requirements:
build:
- ipython >=4
- jupyter_client
- jupyter_core
- notebook
- nbconvert
- nbformat
- python
- traitlets
run:
- ipython >=4
- jupyter_client
- jupyter_core
- notebook
- nbconvert
- nbformat
- python
- traitlets
- yaml
about:
home: https://github.com/ipython-contrib/IPython-notebook-extensions
license: Modified BSD License
summary: 'Notebook extensions for the Jupyter/IPython notebook'

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

@@ -388,9 +388,11 @@ require([
// Activate/Deactivate buttons
build_activate_buttons(ext_id).appendTo(col_left);
var ext_url = get_ext_url(extension);
var active = false;
if (config.data.hasOwnProperty('load_extensions')) active = config.data.load_extensions[ext_url] === true
set_buttons_active(
ext_id,
config.data.load_extensions[ext_url] === true
active
);
if (!extension.hasOwnProperty('Parameters')) continue;
@@ -7,6 +7,38 @@ Activating an extension means it is loaded automatically when working with a not
If you encounter problems with this page, please create an issue at the [ipython-contrib](https://github.com/ipython-contrib/IPython-notebook-extensions) repository.
The documentation below is something you probably don't need to know, if you installed the conda package.
If not, good luck!
## Now where in the world did everything go ?
Jupyter/IPython 4.x works differently than IPython 3.x.
In short
----
* The notebook was split from IPython. You need to install both to run the notebook with IPython now. The easiest way is to use Anaconda and do a `conda install jupyter`
* There are no profiles anymore. You can specify environment variables to change the default, see [Jupyter ML](https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/jupyter/7q02jjksvFU)].
* The configuration has moved to a new place. To find out where, see below.
* There is a kind of automatic upgrade of the configuration files from IPython 3.x to Jupyter.
## So where can I find things now?
To find where the configuration files are, start IPython
```Python
from __future__ import print_function
from jupyter_core.paths import jupyter_config_dir, jupyter_config_path
print(jupyter_config_dir())
print(jupyter_config_path())
```
`jupyter_config_dir()` shows you where your *local* configuration files are, `jupyter_config_path` shows you where Jupyter will look for configuration files. For the notebook, there are two files that will be used:
`jupyter_notebook_config.py` and `jupyter_notebook_config.json`.
The `nbextension` directory has moved to a different location and can be found in one of these directories:
```Python
from __future__ import print_function
from jupyter_core.paths import jupyter_data_dir, jupyter_path
print(jupyter_data_dir())
print(jupyter_path())
```
## Checking/loading notebook extension manually from IPython
You can check if the directory or a file (or list of files) exists:
```Python

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Before

Width:  |  Height:  |  Size: 291 KiB

After

Width:  |  Height:  |  Size: 291 KiB

Before

Width:  |  Height:  |  Size: 424 KiB

After

Width:  |  Height:  |  Size: 424 KiB

Before

Width:  |  Height:  |  Size: 325 KiB

After

Width:  |  Height:  |  Size: 325 KiB

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 185 KiB

Before

Width:  |  Height:  |  Size: 311 KiB

After

Width:  |  Height:  |  Size: 311 KiB

Before

Width:  |  Height:  |  Size: 252 KiB

After

Width:  |  Height:  |  Size: 252 KiB

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Before

Width:  |  Height:  |  Size: 210 KiB

After

Width:  |  Height:  |  Size: 210 KiB

@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
"""
# Copyright (C) 2013
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
@author: juhasch
"""
"""
Tornado web server to
push value received from Pyzmq pull messages
to web browser using a webscocket connection
"""
import time
import os.path
import tornado.web
import tornado.websocket
import tornado.ioloop
import random
import json
import aspell
from zmq.eventloop import ioloop, zmqstream
webport = 8989 # port address for web client
s = aspell.Speller('lang', 'en')
GLOBALS={
'sockets': []
}
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print "open socket"
GLOBALS['sockets'].append(self)
def on_close(self):
print "on_close"
GLOBALS['sockets'].remove(self)
def on_message(self, message):
x=json.loads(message)
text = x['text']
reply = s.check(text)
# reply to request:
# check 1 for OK, 0 for not a valid word
# id cell_id
# line codemirror line number
# start codemirror start position of word
# stop codemirror end position of word
reply = {"check": reply, "id" : x['id'], "line": x['line'],
"start" : x['start'], "end": x['end'] }
self.write_message(reply)
application = tornado.web.Application([
(r"/websocket", WebSocketHandler),
])
if __name__ == "__main__":
ioloop.install()
application.listen(webport)
main_loop = tornado.ioloop.IOLoop.instance()
main_loop.start()
print "Running"

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

@@ -14,20 +14,31 @@ define([
'jquery',
'require',
'base/js/events',
'services/config',
'base/js/utils',
'codemirror/lib/codemirror',
'codemirror/addon/fold/foldgutter',
'codemirror/addon/fold/foldcode',
'codemirror/addon/fold/brace-fold',
'codemirror/addon/fold/indent-fold'
], function(IPython, $, require, events, codemirror) {
], function(IPython, $, require, events, configmod, utils, codemirror) {
"use strict";
if (IPython.version[0] < 3) {
console.log("This extension requires IPython 3.x");
return
}
var foldingKey = { "Alt-F" : toggleFolding };
var HOTKEY = 'Alt-F';
var foldingKey = { HOTKEY : toggleFolding };
var base_url = utils.get_body_data("baseUrl");
var config = new configmod.ConfigSection('notebook', {base_url: base_url});
config.load();
config.loaded.then(function() {
if (config.data.hasOwnProperty('codefolding_hotkey') ){
HOTKEY = config.data.codefolding_hotkey;
foldingKey = {};
foldingKey[HOTKEY] = toggleFolding;
}
});
/*
* Toggle folding on/off at current line
*
@@ -77,7 +88,8 @@ define([
var cell = IPython.notebook.get_selected_cell();
if (cell.code_mirror != cm) {
var cells = IPython.notebook.get_cells();
for(var k in cells){
var ncells = IPython.notebook.ncells();
for(var k=0; k < ncells; k++){
var _cell = cells[k];
if (_cell.code_mirror == cm ) { break; }
}
@@ -93,13 +105,13 @@ define([
function cellFolding(cell) {
if (CodeMirror.fold != undefined) {
var keys = cell.code_mirror.getOption('extraKeys');
cell.code_mirror.setOption('extraKeys', collect(keys, foldingKey ));
cell.code_mirror.setOption('extraKeys', collect(keys, foldingKey ));
var mode = cell.code_mirror.getOption('mode');
/* use indent folding in Python */
if (mode.name == 'ipython' ) {
cell.code_mirror.setOption('foldGutter',{rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.firstline, CodeMirror.fold.magic, CodeMirror.fold.indent) });
cell.code_mirror.setOption('foldGutter',{rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.firstline, CodeMirror.fold.indent) });
} else {
cell.code_mirror.setOption('foldGutter',{rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.firstline, CodeMirror.fold.magic, CodeMirror.fold.brace) });
cell.code_mirror.setOption('foldGutter',{rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.firstline, CodeMirror.fold.brace) });
}
var gutters = cell.code_mirror.getOption('gutters');
var found = jQuery.inArray("CodeMirror-foldgutter", gutters);
@@ -131,16 +143,18 @@ define([
*/
var initGutter = function() {
var cells = IPython.notebook.get_cells();
for(var i in cells){
var ncells = IPython.notebook.ncells();
for (var i=0; i<ncells; i++) {
var cell = cells[i];
if ((cell instanceof IPython.CodeCell)) {
cellFolding(cell);
/* restore folding state if previously saved */
if ( cell.metadata.code_folding != undefined) {
for (var idx in cell.metadata.code_folding) {
for (var idx=0; idx++; idx < cell.metadata.code_folding.length) {
var line = cell.metadata.code_folding[idx];
var opts = cell.code_mirror.state.foldGutter.options;
cell.code_mirror.foldCode(CodeMirror.Pos(line, 0), opts.rangeFinder);
cell.code_mirror.refresh();
}
}
}
@@ -151,7 +165,7 @@ define([
/**
* Load my own CSS file
*
* @param name add CSS file
* @param name off CSS file
*
*/
var load_css = function (name) {
@@ -163,7 +177,7 @@ define([
};
/**
* Called after extension was loaded
* Initialize extension
*
*/
var load_extension = function() {
@@ -171,12 +185,12 @@ define([
/* change default gutter width */
load_css( './foldgutter.css');
/* additional custom codefolding mode */
require(['./firstline-fold', './magic-fold'], initGutter)
require(['./firstline-fold'], initGutter)
};
var codefolding = {
load_ipython_extension : load_extension,
var extension = {
load_ipython_extension : load_extension
};
return codefolding
return extension
});
@@ -1,7 +1,6 @@
This extension adds codefolding functionality from CodeMirror to a codecell.
After clicking on the gutter (left margin of codecell) or typing `Alt+F`, the code gets folded. See the examples below.
The folding status is saved in the cell metadata of the notebook, so reloading of a notebook will restore the folding view.
After clicking on the gutter (left margin of codecell) or typing `Alt+F`, the code gets folded. See the examples below. The folding status is saved in the cell metadata of the notebook, so reloading of a notebook will restore the folding view.
## Supported modes:
Three different folding modes are supported:
@@ -22,8 +21,7 @@ or this:
Other languages like Javascript use brackets to designate code blocks. Codefolding is supported for Javascript in using the `%%javascript` magic in a codecell.
### Firstline Comment Folding
Allows collapsing of Python code cells to a single comment line. This is useful for long codecells. The algorithm simply
looks for a comment in the first line and allows folding in the rest of the cell.
Allows collapsing of Python code cells to a single comment line. This is useful for long codecells. The algorithm simply looks for a comment in the first line and allows folding in the rest of the cell.
![](https://github.com/ipython-contrib/IPython-notebook-extensions/raw/master/wiki-images/codefolding_firstline_unfolded.png)
@@ -31,8 +29,6 @@ The code above can be folded like this:
![](https://raw.github.com/ipython-contrib/IPython-notebook-extensions/master/wiki-images/codefolding_firstline_folded.png)
### Magic Folding
Cell magics in the first line of a cell will also allow cellwide code folding
Installation
============
@@ -42,7 +38,7 @@ Install the master version of the IPython-notebook-extensions repository as expl
Then load the extension from within the IPyton notebook:
```javascript
%%javascript
IPython.load_extensions('nbextensions/usability/codefolding/codefolding');
IPython.load_extensions('IPython-notebook-extensions-master/usability/codefolding/codefolding');
```
## Internals
@@ -54,3 +50,4 @@ cell.metadata.code_folding = [ 3, 20, 33 ]
```
When reloading the IPython notebook, the folding status is restored.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

+170
View File
@@ -0,0 +1,170 @@
// Copyright (c) IPython-Contrib Team.
// Distributed under the terms of the Modified BSD License.
// Allow drag&drop of images into a notebook
// Tested with Firefox and Chrome
define([
'base/js/namespace',
'jquery',
"base/js/events"
], function(IPython, $, events) {
"use strict";
/* http://stackoverflow.com/questions/3231459/create-unique-id-with-javascript */
function uniqueid(){
// always start with a letter (for DOM friendlyness)
var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65));
do {
// between numbers and characters (48 is 0 and 90 is Z (42-48 = 90)
var ascicode=Math.floor((Math.random()*42)+48);
if (ascicode<58 || ascicode>64){
// exclude all chars between : (58) and @ (64)
idstr+=String.fromCharCode(ascicode);
}
} while (idstr.length<32);
return (idstr);
}
var send_to_server = function(name,path,msg) {
if (name == '') {
name = uniqueid() + '.' + msg.match(/data:image\/(\S+);/)[1];
}
path = path.substring(0, path.lastIndexOf('/')) + '/';
if (path === '/') path = '';
var url = '//' + location.host + '/api/contents/' + path + name;
var img = msg.replace(/(^\S+,)/, ''); // strip header
//console.log("send_to_server:", url, img);
var data = {'name': name, 'format':'base64', 'content': img, 'type': 'file'};
var settings = {
processData : false,
cache : false,
type : "PUT",
dataType : "json",
data : JSON.stringify(data),
headers : {'Content-Type': 'text/plain'},
async : false,
success : function (data, status, xhr) {
var new_cell = IPython.notebook.insert_cell_below('markdown');
var str = '<img src="' + name + '"/>';
new_cell.set_text(str);
new_cell.execute();
},
error : function() {console.log('Data transfer for drag-and-drop failed.'); }
};
$.ajax(url, settings);
};
/* the dragover event needs to be canceled to allow firing the drop event */
window.addEventListener('dragover', function(event){
if (event.preventDefault) {
event.preventDefault();
}
});
/* allow dropping an image in notebook */
window.addEventListener('drop', function(event){
var cell = IPython.notebook.get_selected_cell();
event.preventDefault();
if(event.stopPropagation) {event.stopPropagation();}
if (event.dataTransfer.items != undefined) {
/* Chrome here */
var items = event.dataTransfer.items;
for (var i = 0; i < items.length; i++) {
/* data coming from local file system, must be an image to allow dropping*/
if (items[i].kind == 'file' && items[i].type.indexOf('image/') !== -1) {
var blob = items[i].getAsFile();
var filename = blob.name;
var reader = new FileReader();
reader.onload = ( function(evt) {
send_to_server(filename, IPython.notebook.notebook_path, evt.target.result);
if(event.stopPropagation) {event.stopPropagation();}
} );
reader.readAsDataURL(blob);
} else {
console.log("Unsupported type:", items[i].kind);
}
}
} else {
/* Firefox here */
var files = event.dataTransfer.files;
if (files.length == 0) {
var filename = event.dataTransfer.getData('application/x-moz-file-promise-dest-filename');
var data = event.dataTransfer.getData('text/plain');
if (filename.length == 0) {
url = "";
filename = '';
} else {
url = data;
data = "";
}
/* data coming from browser:
* url - image is given as an url
* data - image is a base64 blob
*/
//console.log("type:",url," name:", filename," path:", IPython.notebook.notebook_path," url:", url);
send_to_server(filename, IPython.notebook.notebook_path, data);
return;
}
/* data coming from local file system, must be an image to allow dropping*/
for (var i=0; i < files.length; i++) {
var blob = event.dataTransfer.files[0];
if (blob.type.indexOf('image/') !== -1) {
var filename = blob.name;
var url = event.view.location.origin;
var reader = new FileReader();
reader.onload = ( function(evt) {
//console.log("file"," name:", filename," path:", IPython.notebook.notebook_path," url:", url);
send_to_server(filename, IPython.notebook.notebook_path, evt.target.result);
event.preventDefault();
} );
reader.readAsDataURL(blob);
} else {
console.log("Unsupported type:", blob.type);
}
}
}
});
/*
* make sure we do not drop images into a codemirror text field
*/
var checktype = function(cm,event) {
if (event.dataTransfer.items != undefined)
{
event.codemirrorIgnore = true;
}
var blob = event.dataTransfer.files[0];
if (event.dataTransfer.files.length > 0 && blob.type.indexOf('image/') !== -1) {
event.codemirrorIgnore = true;
}
};
var create_cell = function (event,nbcell,nbindex) {
var cell = nbcell.cell;
if ((cell instanceof IPython.CodeCell)) {
cell.code_mirror.on('drop', checktype);
}
};
var cells = IPython.notebook.get_cells();
for(var i in cells){
var cell = cells[i];
if ((cell instanceof IPython.CodeCell)) {
cell.code_mirror.on('drop', checktype);
}
}
var load_ipython_extension = function() {
events.on('create.Cell', create_cell);
};
var extension = {
load_ipython_extension : load_ipython_extension
};
return extension;
});
+25
View File
@@ -0,0 +1,25 @@
This IPython notebook extension allows dragging&dropping images from the desktop or other programs into a notebook. A new markdown cell is created below the currently selected cell and the image is embedded.
The notebook has been tested with Firefox and Chrome.
A demo video showing drag&drop of images is here:
http://youtu.be/buAL1bTZ73c
## Installation
From IPython simply call
```python
import IPython
IPython.html.nbextensions.install_nbextension('https://raw.githubusercontent.com/ipython-contrib/IPython-notebook-extensions/master/usability/dragdrop/main.js')
```
Then load the extension from within the IPyton notebook:
```javascript
%%javascript
IPython.load_extensions('drag-and-drop');
```
Alternatively, you can add the load command to your `custom.js`.
## Internals
The image will be uploaded to the server into the directory where your notebook resides. This means, the image is not copied into the notebook itself, it will only be linked to. The markdown cell in the notebook will contain this tag:
`<img src="http://127.0.0.1:8888/notebooks/myimage.png"/>`
If you run `nbconvert` to generate a HTML file, this image will remain outside of the html file. You can embedd all images by calling `nbconvert` with the option `--post=embed.EmbedPostProcessor`. The file `embed.py`, located in the same directory of this extension needs to be in `PYTHONPATH` to be found.
@@ -18,7 +18,7 @@ define(["require", "jquery", "base/js/namespace", "base/js/events"], function (r
var patchCodecellExecute = function() {
console.log('patching codecell to trigger ExecuteCell.ExecuteTime');
IPython.CodeCell.prototype.old_execute = IPython.CodeCell.prototype.execute
IPython.CodeCell.prototype.old_execute = IPython.CodeCell.prototype.execute;
IPython.CodeCell.prototype.execute = function () {
this.old_execute(arguments);
@@ -165,14 +165,18 @@ define(["require", "jquery", "base/js/namespace", "base/js/events"], function (r
}
};
var load_ipython_extension = function() {
patchCodecellExecute();
patchCodecellExecute();
events.on('ExecuteCell.ExecuteTime', executionStartTime);
events.on('kernel_idle.Kernel', executionEndTime);
events.on('ExecuteCell.ExecuteTime',executionStartTime);
events.on('kernel_idle.Kernel', executionEndTime);
$("head").append($("<link rel='stylesheet' href='" + require.toUrl("./ExecuteTime.css") + "' type='text/css' />"));
create_menu();
};
$("head").append($("<link rel='stylesheet' href='" + require.toUrl("./ExecuteTime.css") + "' type='text/css' />"));
create_menu();
console.log('Execute Timings loaded');
var extension = {
load_ipython_extension : load_ipython_extension
};
return extension;
});

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

@@ -2,21 +2,18 @@ This extension displays when the last execution of a cell occurred and how long
## Display
Every executed cell is extended with a new area, attached at the bottom of the input area, that displays when the user
started the last execution of this cell. When the kernel finishes to execute a cell, this area is update with the duration.
Every executed cell is extended with a new area, attached at the bottom of the input area, that displays when the user started the last execution of this cell. When the kernel finishes to execute a cell, this area is update with the duration.
![](https://github.com/ipython-contrib/IPython-notebook-extensions/raw/master/wiki-images/execution-timings-box.png)
## Toggling
The timings area can be hide by double clicking on it or using the option in the cell menu. The menu toggle
timings->All hides (resp. shows) all the possible timings area if the first cell is displayed (resp. hidden).
The timings area can be hide by double clicking on it or using the option in the cell menu. The menu toggle timings->All hides (resp. shows) all the possible timings area if the first cell is displayed (resp. hidden).
![](https://github.com/ipython-contrib/IPython-notebook-extensions/raw/master/wiki-images/execution-timings-menu.png)
## Internals
To be sure that the kernel is run intentionally by executing a codecell, codecell.prototype.execute() is overloaded
and a new event 'ExecuteCell.ExecuteTime' is fired, that this extension catches to display the start time. We use the event 'status_idle.Kernel' to know when the kernel finished the execution of the cell.
To be sure that the kernel is run intentionally by executing a codecell, codecell.prototype.execute() is overloaded and a new event 'ExecuteCell.ExecuteTime' is fired, that this extension catches to display the start time. We use the event 'status_idle.Kernel' to know when the kernel finished the execution of the cell.
## Installation
Copy `ExecuteTime.{js,css}`, and add `require(['/static/custom/ExecuteTime.js'])` to `custom.js` in your profile's `/static/custom` directory, so it looks like this:
@@ -28,5 +25,4 @@ $([IPython.events]).on('app_initialized.NotebookApp', function(){
```
## TODO
The timings information could be stored into the notebook and displayed when it is loaded. Where these information s
hould be stored is still to be decided (maybe in the metadata).
The timings information could be stored into the notebook and displayed when it is loaded. Where these information should be stored is still to be decided (maybe in the metadata).
@@ -1,7 +1,7 @@
Type: IPython Notebook Extension
Name: Search-Replace
Description: Search and replace
Link: https://github.com/ipython-contrib/IPython-notebook-extensions/wiki
Name: Exercise
Description: Exercise TEST
Link: https://github.com/ipython-contrib/IPython-notebook-extensions/wiki/
Icon: icon.png
Main: main.js
Compatibility: 3.x
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -1,14 +1,15 @@
// Hide or diplay solutions in a notebook
// Copyright (c) IPython-Contrib Team.
// Distributed under the terms of the Modified BSD License.
// To define a solution, select all cells of a solution using shift button and mouse
// All cells will be hidden, except the first one
// A hide/unhide symbol will be displayed. Click on it and the solution will be displayed/hidden
// Hide or diplay solutions in a notebook
define([
'base/js/namespace',
'jquery',
"base/js/events",
], function(IPython, $, events) {
'require',
'base/js/events',
'nbextensions/usability/rubberband/main'
], function(IPython, $, require, events, rubberband) {
"use strict";
/**
@@ -18,21 +19,21 @@ define([
* @param ev {Event} jquery event
*/
function click_solution_lock(ev) {
var cell=IPython.notebook.get_selected_cell()
var is_locked = cell.element.find('#lock').hasClass('fa-plus-square-o')
var cell=IPython.notebook.get_selected_cell();
var is_locked = cell.element.find('#lock').hasClass('fa-plus-square-o');
if (is_locked == true) {
cell.element.find('#lock').removeClass('fa-plus-square-o')
cell.element.find('#lock').addClass('fa-minus-square-o')
cell.element.find('#lock').removeClass('fa-plus-square-o');
cell.element.find('#lock').addClass('fa-minus-square-o');
while (cell.metadata.solution == true) {
IPython.notebook.select_next();
cell.element.show();
cell = IPython.notebook.get_selected_cell()
}
} else {
cell.element.find('#lock').removeClass('fa-minus-square-o')
cell.element.find('#lock').addClass('fa-plus-square-o')
cell.element.find('#lock').removeClass('fa-minus-square-o');
cell.element.find('#lock').addClass('fa-plus-square-o');
IPython.notebook.select_next();
cell = IPython.notebook.get_selected_cell()
cell = IPython.notebook.get_selected_cell();
while (cell.metadata.solution == true) {
cell.element.hide();
IPython.notebook.select_next();
@@ -49,48 +50,48 @@ define([
*/
function hide_solutions() {
// first check if lock symbol is already present in selected cell, if yes, remove it
var cell=IPython.notebook.get_selected_cell()
var has_lock = cell.element.find('#lock').is('div')
var cell=IPython.notebook.get_selected_cell();
var has_lock = cell.element.find('#lock').is('div');
if (has_lock === true) {
cell.element.find('#lock').remove()
cell.element.find('#lock').remove();
while (cell.metadata.solution == true) {
delete cell.metadata.solution
cell.element.show()
IPython.notebook.select_next()
delete cell.metadata.solution;
cell.element.show();
IPython.notebook.select_next();
cell = IPython.notebook.get_selected_cell()
}
} else {
// find first cell with solution
var start_cell_i // = undefined
var cells = IPython.notebook.get_cells()
var start_cell_i; // = undefined
var cells = IPython.notebook.get_cells();
for(var i in cells){
var cell = cells[i]
var cell = cells[i];
if (typeof cell.metadata.selected != undefined && cell.metadata.selected === true) {
start_cell_i = i
console.log("selected start cell:",i)
start_cell_i = i;
console.log("selected start cell:", i);
break
}
}
IPython.notebook.select(start_cell_i)
IPython.notebook.select(start_cell_i);
if (cell.metadata.selected == true) {
var el = $('<div id="lock" class="fa fa-plus-square-o">')
cell.element.prepend(el)
cell.metadata.solution = true
var el = $('<div id="lock" class="fa fa-plus-square-o">');
cell.element.prepend(el);
cell.metadata.solution = true;
cell.element.css({"background-color": "#ffffff"});
delete cell.metadata.selected
delete cell.metadata.selected;
el.click(click_solution_lock)
el.click(click_solution_lock);
IPython.notebook.select_next();
cell = IPython.notebook.get_selected_cell()
console.log("new cell:", IPython.notebook.get_selected_index())
cell = IPython.notebook.get_selected_cell();
console.log("new cell:", IPython.notebook.get_selected_index());
while (cell.metadata.selected == true) {
cell.element.css({"background-color": "#ffffff"});
delete cell.metadata.selected
delete cell.metadata.selected;
cell.element.hide();
cell.metadata.solution = true
cell.metadata.solution = true;
IPython.notebook.select_next();
cell = IPython.notebook.get_selected_cell()
cell = IPython.notebook.get_selected_cell();
console.log("new cell(i):",IPython.notebook.get_selected_index())
}
}
@@ -105,7 +106,7 @@ define([
callback : function () {
hide_solutions();
}
},
}
]);
/**
@@ -120,22 +121,21 @@ define([
link.type = "text/css";
link.rel = "stylesheet";
link.href = require.toUrl(name);
console.log(link);
document.getElementsByTagName("head")[0].appendChild(link);
};
load_css('/nbextensions/testing/exercise/main.css');
var exercise_wrapper = $('<div id="dragmask" class="highlight-drag"></div>')
$("#header").append(exercise_wrapper)
load_css('./main.css');
var exercise_wrapper = $('<div id="dragmask" class="highlight-drag"></div>');
$("#header").append(exercise_wrapper);
/**
* Display existing solutions at startup
*
*/
var cells = IPython.notebook.get_cells()
var found_solution = false
var cells = IPython.notebook.get_cells();
var found_solution = false;
for(var i in cells){
var cell = cells[i]
var cell = cells[i];
if (found_solution == true && typeof cell.metadata.solution != undefined && cell.metadata.solution === true) {
cell.element.hide()
} else {
@@ -143,10 +143,11 @@ define([
}
if (found_solution == false && typeof cell.metadata.solution != undefined && cell.metadata.solution === true) {
// hide solution
var el = $('<div id="lock" class="fa fa-plus-square-o">')
cell.element.prepend(el)
el.click( click_solution_lock)
var el = $('<div id="lock" class="fa fa-plus-square-o">');
cell.element.prepend(el);
el.click( click_solution_lock);
found_solution = true
}
rubberband.load_ipython_extension()
}
})
});

Some files were not shown because too many files have changed in this diff Show More