mirror of
https://github.com/wassname/jupyter_contrib_nbextensions.git
synced 2026-08-11 11:19:52 +08:00
Use contents service
Use new contents service to upload graphics, replacing the separate websocket server.
This commit is contained in:
+114
-125
@@ -2,137 +2,126 @@
|
||||
// works with images and notebook cells (MIME-type 'notebook-cell/json')
|
||||
|
||||
"using strict";
|
||||
define( function () {
|
||||
var load_ipython_extension = function () {
|
||||
if (window.chrome == undefined) return;
|
||||
|
||||
chrome_clipboard = function() {
|
||||
/* 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);
|
||||
|
||||
if (window.chrome == undefined) return;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* receive url of graphics from websocket */
|
||||
dragdrop_event = function(evt){
|
||||
console.log("Websock-Event:", evt);
|
||||
var obj = $.parseJSON(evt.data);
|
||||
if (obj.status == "OK") {
|
||||
var new_cell = IPython.notebook.insert_cell_below('markdown');
|
||||
var filename = obj.name;
|
||||
var str = '<img src="' + filename + '"/>';
|
||||
new_cell.set_text(str);
|
||||
new_cell.rendered = false;
|
||||
new_cell.render();
|
||||
return (idstr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* override clipboard 'paste' and insert new cell from json data in clipboard
|
||||
*/
|
||||
window.addEventListener('paste', function(event){
|
||||
var cell = IPython.notebook.get_selected_cell();
|
||||
if (cell.mode == "command" ) {
|
||||
event.preventDefault();
|
||||
var items = event.clipboardData.items;
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
console.log("items:", items[i].type);
|
||||
if (items[i].type == 'notebook-cell/json') {
|
||||
/* json data adds a new notebook cell */
|
||||
var data = event.clipboardData.getData('notebook-cell/json');
|
||||
var new_cell_data = JSON.parse(data);
|
||||
var new_cell = IPython.notebook.insert_cell_below(new_cell_data.cell_type);
|
||||
new_cell.fromJSON(new_cell_data);
|
||||
} else if (items[i].type.indexOf('image/') !== -1) {
|
||||
/* images are transferred to the server as file and linked to */
|
||||
var blob = items[i].getAsFile();
|
||||
var reader = new FileReader();
|
||||
reader.onload = ( function(evt) {
|
||||
var filename = uniqueid();
|
||||
var msg = JSON.stringify({"type":"file",
|
||||
"name":filename,
|
||||
"path":IPython.notebook.notebook_path,
|
||||
"url" : "",
|
||||
"data": evt.target.result});
|
||||
IPython.notebook.ws_dragdrop.send(msg);
|
||||
event.preventDefault();
|
||||
} );
|
||||
reader.readAsDataURL(blob);
|
||||
|
||||
send_to_server = function(name,path,msg) {
|
||||
if (name == '') {
|
||||
name = uniqueid() + '.' + msg.match(/data:image\/(\S+);/)[1];
|
||||
}
|
||||
var url = 'http://' + location.host + '/api/contents/' + path + '/' + name;
|
||||
var img = msg.replace(/(^\S+,)/, ''); // strip header
|
||||
// console.log("send_to_server:", url, msg);
|
||||
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();
|
||||
//new_cell.select();
|
||||
},
|
||||
error : function() {console.log('fail'); },
|
||||
};
|
||||
$.ajax(url, settings);
|
||||
}
|
||||
/*
|
||||
* override clipboard 'paste' and insert new cell from json data in clipboard
|
||||
*/
|
||||
window.addEventListener('paste', function(event){
|
||||
var cell = IPython.notebook.get_selected_cell();
|
||||
if (cell.mode == "command" ) {
|
||||
event.preventDefault();
|
||||
var items = event.clipboardData.items;
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
console.log("items:", items[i].type);
|
||||
if (items[i].type == 'notebook-cell/json') {
|
||||
/* json data adds a new notebook cell */
|
||||
var data = event.clipboardData.getData('notebook-cell/json');
|
||||
var new_cell_data = JSON.parse(data);
|
||||
var new_cell = IPython.notebook.insert_cell_below(new_cell_data.cell_type);
|
||||
new_cell.fromJSON(new_cell_data);
|
||||
} else if (items[i].type.indexOf('image/') !== -1) {
|
||||
/* images are transferred to the server as file and linked to */
|
||||
var blob = items[i].getAsFile();
|
||||
var reader = new FileReader();
|
||||
reader.onload = ( function(evt) {
|
||||
var filename = '';
|
||||
send_to_server(filename, IPython.notebook.notebook_path, evt.target.result);
|
||||
event.preventDefault();
|
||||
} );
|
||||
reader.readAsDataURL(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* override clipboard 'copy' and copy current cell as json and text to clipboard
|
||||
*/
|
||||
window.addEventListener('copy', function(event){
|
||||
|
||||
var cell = IPython.notebook.get_selected_cell();
|
||||
if (cell.mode == "command") {
|
||||
var sel = window.getSelection();
|
||||
if (sel.type == "Range") return; /* default: copy marked text */
|
||||
event.preventDefault();
|
||||
var j = cell.toJSON();
|
||||
var json = JSON.stringify(j);
|
||||
var text = cell.code_mirror.getValue();
|
||||
/* copy cell as json and cell contents as text */
|
||||
event.clipboardData.setData('notebook-cell/json',json);
|
||||
event.clipboardData.setData("Text", text);
|
||||
}
|
||||
});
|
||||
/*
|
||||
* override clipboard 'copy' and copy current cell as json and text to clipboard
|
||||
*/
|
||||
window.addEventListener('copy', function(event){
|
||||
|
||||
var cell = IPython.notebook.get_selected_cell();
|
||||
if (cell.mode == "command") {
|
||||
var sel = window.getSelection();
|
||||
if (sel.type == "Range") return; /* default: copy marked text */
|
||||
event.preventDefault();
|
||||
var j = cell.toJSON();
|
||||
var json = JSON.stringify(j);
|
||||
var text = cell.code_mirror.getValue();
|
||||
/* copy cell as json and cell contents as text */
|
||||
event.clipboardData.setData('notebook-cell/json',json);
|
||||
event.clipboardData.setData("Text", text);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* override clipboard 'cut' and copy current cell as json and text to clipboard
|
||||
*/
|
||||
window.addEventListener('cut', function(event){
|
||||
|
||||
var cell = IPython.notebook.get_selected_cell();
|
||||
if (cell.mode == "command" ) {
|
||||
var sel = window.getSelection();
|
||||
if (sel.type == "Range") return; /* default: cut marked text */
|
||||
event.preventDefault();
|
||||
var j = cell.toJSON();
|
||||
var json = JSON.stringify(j);
|
||||
var text = cell.code_mirror.getValue();
|
||||
/* copy cell as json and cell contents as text */
|
||||
event.clipboardData.setData('notebook-cell/json',json);
|
||||
event.clipboardData.setData("Text", text);
|
||||
IPython.notebook.delete_cell(IPython.notebook.find_cell_index(cell));
|
||||
}
|
||||
});
|
||||
/*
|
||||
* override clipboard 'cut' and copy current cell as json and text to clipboard
|
||||
*/
|
||||
window.addEventListener('cut', function(event){
|
||||
|
||||
var cell = IPython.notebook.get_selected_cell();
|
||||
if (cell.mode == "command" ) {
|
||||
var sel = window.getSelection();
|
||||
if (sel.type == "Range") return; /* default: cut marked text */
|
||||
event.preventDefault();
|
||||
var j = cell.toJSON();
|
||||
var json = JSON.stringify(j);
|
||||
var text = cell.code_mirror.getValue();
|
||||
/* copy cell as json and cell contents as text */
|
||||
event.clipboardData.setData('notebook-cell/json',json);
|
||||
event.clipboardData.setData("Text", text);
|
||||
IPython.notebook.delete_cell(IPython.notebook.find_cell_index(cell));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function callback(out_data)
|
||||
{
|
||||
var ul = out_data.content.data;
|
||||
var webport = eval(ul['text/plain'])
|
||||
console.log("webport:",webport);
|
||||
var wsUri = "ws://" + document.domain + ":" + webport + "/"+ "websocket";
|
||||
var ws_dragdrop = new WebSocket(wsUri);
|
||||
IPython.notebook.ws_dragdrop = ws_dragdrop;
|
||||
ws_dragdrop.onmessage = dragdrop_event;
|
||||
}
|
||||
return {
|
||||
load_ipython_extension : load_ipython_extension,
|
||||
};
|
||||
});
|
||||
|
||||
function getport()
|
||||
{
|
||||
var code = 'drag_and_drop_webport';
|
||||
var callbacks = { iopub : { output: callback } };
|
||||
|
||||
IPython.notebook.kernel.execute(code, callbacks, {silent: false});
|
||||
}
|
||||
|
||||
|
||||
$([IPython.events]).on('create.Cell',create_cell);
|
||||
$([IPython.events]).on('status_started.Kernel',function() { getport();});
|
||||
|
||||
}();
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# start websocket server for drag-and-drop extension
|
||||
|
||||
drag_and_drop_webport = get_ipython().config['DragDrop']['port']
|
||||
|
||||
def start_drag_and_drop():
|
||||
c = get_ipython()
|
||||
nb_dir = get_ipython().config['FileNotebookManager']['notebook_dir']
|
||||
newpath = os.path.normpath(c.config['NotebookApp']['extra_static_paths'][0]+'/custom/dragdrop/')
|
||||
sys.path.insert(0, newpath)
|
||||
|
||||
import drag_and_drop
|
||||
drag_and_drop.start_server(drag_and_drop_webport, nb_dir)
|
||||
|
||||
start_drag_and_drop()
|
||||
+153
-175
@@ -1,80 +1,108 @@
|
||||
// add drag&drop functionality
|
||||
// Allow drag&drop of images into a notebook
|
||||
// Tested with Firefox and Chrome
|
||||
|
||||
|
||||
"using strict";
|
||||
define( function () {
|
||||
var load_ipython_extension = function () {
|
||||
|
||||
drag_and_drop = function() {
|
||||
|
||||
|
||||
/* 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);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* receive url of graphics from websocket */
|
||||
dragdrop_event = function(evt){
|
||||
console.log("Websock-Event:", evt);
|
||||
var obj = $.parseJSON(evt.data);
|
||||
if (obj.status == "OK") {
|
||||
var new_cell = IPython.notebook.insert_cell_below('markdown');
|
||||
var filename = obj.name;
|
||||
var str = '<img src="' + filename + '"/>';
|
||||
new_cell.set_text(str);
|
||||
new_cell.rendered = false;
|
||||
new_cell.render();
|
||||
return (idstr);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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){
|
||||
if (IPython.notebook.mode === "edit") return;
|
||||
// console.log("drop event x:",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) {
|
||||
console.log("name:",filename)
|
||||
var msg = JSON.stringify({"type":"file",
|
||||
"name":filename,
|
||||
"path":IPython.notebook.notebook_path,
|
||||
"url" : "",
|
||||
"data": evt.target.result});
|
||||
IPython.notebook.ws_dragdrop.send(msg);
|
||||
event.preventDefault();
|
||||
|
||||
send_to_server = function(name,path,msg) {
|
||||
if (name == '') {
|
||||
name = uniqueid() + '.' + msg.match(/data:image\/(\S+);/)[1];
|
||||
}
|
||||
var url = 'http://' + location.host + '/api/contents/' + path + '/' + name;
|
||||
var img = msg.replace(/(^\S+,)/, ''); // strip header
|
||||
//console.log("send_to_server:", url, img);
|
||||
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();
|
||||
//new_cell.select();
|
||||
},
|
||||
error : function() {console.log('fail'); },
|
||||
};
|
||||
$.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){
|
||||
// console.log("drop event x:",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);
|
||||
event.preventDefault();
|
||||
} );
|
||||
reader.readAsDataURL(blob);
|
||||
} else if (items[i].kind == 'string') {
|
||||
/* data coming from browser */
|
||||
reader.readAsDataURL(blob);
|
||||
} else if (items[i].kind == 'string') {
|
||||
/* data coming from browser */
|
||||
var data = event.dataTransfer.getData('text/plain');
|
||||
if (data[0] == 'd') {
|
||||
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("file"," name:", filename," path:", IPython.notebook.notebook_path," url:", url);
|
||||
send_to_server(filename, IPython.notebook.notebook_path, data);
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} 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 (data[0] == 'd') {
|
||||
if (filename.length == 0) {
|
||||
url = "";
|
||||
filename = uniqueid();
|
||||
filename = '';
|
||||
} else {
|
||||
url = data;
|
||||
data = "";
|
||||
@@ -83,116 +111,66 @@ drag_and_drop = function() {
|
||||
* url - image is given as an url
|
||||
* data - image is a base64 blob
|
||||
*/
|
||||
var msg = JSON.stringify({"type":"url",
|
||||
"name":filename,
|
||||
"path":IPython.notebook.notebook_path,
|
||||
"url" : url,
|
||||
"data": data});
|
||||
IPython.notebook.ws_dragdrop.send(msg);
|
||||
//console.log("type:",url," name:", filename," path:", IPython.notebook.notebook_path," url:", url);
|
||||
send_to_server(filename, IPython.notebook.notebook_path, data);
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} 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 = uniqueid();
|
||||
} else {
|
||||
url = data;
|
||||
data = "";
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
var msg = JSON.stringify({"type":"url",
|
||||
"name":filename,
|
||||
"path":IPython.notebook.notebook_path,
|
||||
"url" : url,
|
||||
"data": data});
|
||||
IPython.notebook.ws_dragdrop.send(msg);
|
||||
event.preventDefault();
|
||||
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);
|
||||
var msg = JSON.stringify({"type":"file",
|
||||
"name":filename,
|
||||
"path":IPython.notebook.notebook_path,
|
||||
"url" : url,
|
||||
"data": evt.target.result});
|
||||
IPython.notebook.ws_dragdrop.send(msg);
|
||||
event.preventDefault();
|
||||
} );
|
||||
reader.readAsDataURL(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* make sure we do not drop images into a codemirror text field
|
||||
*/
|
||||
checktype = function(cm,event) {
|
||||
if (event.dataTransfer.items != undefined)
|
||||
{
|
||||
evt.codemirrorIgnore = true;
|
||||
}
|
||||
var blob = evt.dataTransfer.files[0];
|
||||
|
||||
if (blob.type.indexOf('image/') !== -1) {
|
||||
evt.codemirrorIgnore = true;
|
||||
});
|
||||
|
||||
/*
|
||||
* make sure we do not drop images into a codemirror text field
|
||||
*/
|
||||
checktype = function(cm,event) {
|
||||
if (event.dataTransfer.items != undefined)
|
||||
{
|
||||
evt.codemirrorIgnore = true;
|
||||
}
|
||||
var blob = evt.dataTransfer.files[0];
|
||||
|
||||
if (blob.type.indexOf('image/') !== -1) {
|
||||
evt.codemirrorIgnore = true;
|
||||
}
|
||||
}
|
||||
|
||||
create_cell = function (event,nbcell,nbindex) {
|
||||
var cell = nbcell.cell;
|
||||
if ((cell instanceof IPython.CodeCell)) {
|
||||
cell.code_mirror.on('drop', checktype);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
function callback(out_data)
|
||||
{
|
||||
var ul = out_data.content.data;
|
||||
var webport = eval(ul['text/plain'])
|
||||
console.log("Graphics webport:",webport);
|
||||
var wsUri = "ws://" + document.domain + ":" + webport + "/"+ "websocket";
|
||||
var ws_dragdrop = new WebSocket(wsUri);
|
||||
IPython.notebook.ws_dragdrop = ws_dragdrop;
|
||||
ws_dragdrop.onmessage = dragdrop_event;
|
||||
}
|
||||
|
||||
function getport()
|
||||
{
|
||||
var code = 'drag_and_drop_webport';
|
||||
var callbacks = { iopub : { output: callback } };
|
||||
|
||||
IPython.notebook.kernel.execute(code, callbacks, {silent: false});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$([IPython.events]).on('create.Cell',create_cell);
|
||||
$([IPython.events]).on('status_started.Kernel',function() { getport();});
|
||||
}();
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
$([IPython.events]).on('create.Cell',create_cell);
|
||||
};
|
||||
|
||||
return {
|
||||
load_ipython_extension : load_ipython_extension,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
# -*- 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
|
||||
|
||||
Configuration in ipython_notebook_config.py:
|
||||
c.DragDrop.port = 8901
|
||||
|
||||
"""
|
||||
|
||||
import time
|
||||
import os.path
|
||||
import sys, getopt
|
||||
|
||||
import numpy as np
|
||||
|
||||
import tornado.web
|
||||
import tornado.websocket
|
||||
import tornado.ioloop
|
||||
|
||||
import random
|
||||
import json
|
||||
import base64
|
||||
import hashlib
|
||||
|
||||
from zmq.eventloop import ioloop, zmqstream
|
||||
|
||||
webport = 0
|
||||
nb_dir = ''
|
||||
|
||||
GLOBALS={
|
||||
'sockets': []
|
||||
}
|
||||
|
||||
# http://stackoverflow.com/questions/273192/check-if-a-directory-exists-and-create-it-if-necessary
|
||||
def ensure_dir(f):
|
||||
d = os.path.dirname(f)
|
||||
if not os.path.exists(d):
|
||||
os.makedirs(d)
|
||||
|
||||
def md5sum(fname, block_size=2**20):
|
||||
f = open(fname, 'rb')
|
||||
md5 = hashlib.md5()
|
||||
while True:
|
||||
data = f.read(block_size)
|
||||
if not data:
|
||||
break
|
||||
md5.update(data)
|
||||
f.close()
|
||||
return md5.hexdigest()
|
||||
|
||||
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)
|
||||
print "Data received"
|
||||
url = x['url']
|
||||
if len(url) == 0:
|
||||
print "Base64"
|
||||
filename = x['name']
|
||||
print "Filename: %s" % filename
|
||||
|
||||
path = nb_dir + u'\\' + x['path'] + u'\\images\\'
|
||||
print "Path: %s" %path
|
||||
|
||||
ensure_dir(path)
|
||||
png_b64 = x['data']
|
||||
data = png_b64.split(',') # [0] is header, [1] b64 data
|
||||
png = base64.b64decode(data[1])
|
||||
print "Filename: %s" % filename
|
||||
# check if file exists
|
||||
if os.path.exists(path+filename):
|
||||
print('File %s already exists')
|
||||
# compare md5sum
|
||||
md5_file = md5sum(path+filename)
|
||||
# print('md5sum of file is %s' % md5_file)
|
||||
d = hashlib.md5()
|
||||
d.update(png)
|
||||
md5_websocket = d.hexdigest()
|
||||
# print('md5sum of dropped image is is %s' % md5_websocket)
|
||||
if md5_file != md5_websocket:
|
||||
i = 0
|
||||
while True:
|
||||
|
||||
if not os.path.exists('%s%0d_%s' % (path, i, filename)):
|
||||
break
|
||||
filename = '%0d_%s' % (i, filename)
|
||||
f = open(path+filename, 'wb')
|
||||
f.write(png)
|
||||
f.close()
|
||||
else:
|
||||
f = open(path+filename, 'wb')
|
||||
f.write(png)
|
||||
f.close()
|
||||
status = "OK"
|
||||
reply = {"status": status, "name": 'images/' + filename }
|
||||
self.write_message(reply)
|
||||
else:
|
||||
status = "OK"
|
||||
reply = {"status": status, "name": url }
|
||||
self.write_message(reply)
|
||||
|
||||
application = tornado.web.Application([
|
||||
(r"/websocket", WebSocketHandler),
|
||||
])
|
||||
|
||||
|
||||
def main(argv):
|
||||
global webport, nb_dir
|
||||
#try:
|
||||
opts, args = getopt.getopt(argv,"hp:d:",["port=","directory="])
|
||||
if opts == []:
|
||||
print 'drag-and-drop.py -p <port> -d <directory>'
|
||||
sys.exit(2)
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt == '-h':
|
||||
print 'drag-and-drop.py -p <port> -d <directory>'
|
||||
sys.exit()
|
||||
elif opt in ("-p", "--port"):
|
||||
webport = int(arg)
|
||||
elif opt in ("-d", "--directory"):
|
||||
nb_dir = arg
|
||||
|
||||
|
||||
print 'webport is "', webport
|
||||
print 'notebook directory is "', nb_dir
|
||||
|
||||
if webport < 1000 or webport > 65535:
|
||||
print('Illegal webport adress %d' % webport)
|
||||
sys.exit(2)
|
||||
|
||||
if not os.path.exists(nb_dir):
|
||||
print('Directory %s does not exist' % nb_dir)
|
||||
sys.exit(2)
|
||||
|
||||
ioloop.install()
|
||||
try:
|
||||
application.listen(webport)
|
||||
except:
|
||||
print('Port %d already in use!' % webport)
|
||||
exit()
|
||||
main_loop = tornado.ioloop.IOLoop.instance()
|
||||
main_loop.start()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
||||
@@ -1,147 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
# Copyright (C) 2014
|
||||
# Distributed under the terms of the BSD License.
|
||||
"""
|
||||
|
||||
"""
|
||||
Tornado websocket server to save images received from web browser and reply
|
||||
with URL of stored image.
|
||||
This is required for drag&drop of images in the IPython notebook
|
||||
|
||||
The websocket port can be configured in ipython_notebook_config.py:
|
||||
c.DragDrop.port = 8901
|
||||
|
||||
"""
|
||||
|
||||
import time
|
||||
import os.path
|
||||
import sys, getopt
|
||||
|
||||
import numpy as np
|
||||
|
||||
import tornado.web
|
||||
import tornado.websocket
|
||||
import tornado.ioloop
|
||||
|
||||
import random
|
||||
import json
|
||||
import base64
|
||||
import hashlib
|
||||
from multiprocessing import Process
|
||||
from zmq.eventloop import ioloop, zmqstream
|
||||
|
||||
webport = 0
|
||||
nb_dir = ''
|
||||
|
||||
GLOBALS={
|
||||
'sockets': []
|
||||
}
|
||||
|
||||
# http://stackoverflow.com/questions/273192/check-if-a-directory-exists-and-create-it-if-necessary
|
||||
def ensure_dir(f):
|
||||
d = os.path.dirname(f)
|
||||
if not os.path.exists(d):
|
||||
os.makedirs(d)
|
||||
|
||||
def md5sum(fname, block_size=2**20):
|
||||
f = open(fname, 'rb')
|
||||
md5 = hashlib.md5()
|
||||
while True:
|
||||
data = f.read(block_size)
|
||||
if not data:
|
||||
break
|
||||
md5.update(data)
|
||||
f.close()
|
||||
return md5.hexdigest()
|
||||
|
||||
class WebSocketHandler(tornado.websocket.WebSocketHandler):
|
||||
""" Handle websocket connections from web browser
|
||||
"""
|
||||
def open(self):
|
||||
GLOBALS['sockets'].append(self)
|
||||
|
||||
def on_close(self):
|
||||
GLOBALS['sockets'].remove(self)
|
||||
|
||||
def on_message(self, message):
|
||||
""" Receive image from web browser
|
||||
Save it to the local 'images' directory under it's name.
|
||||
If filename already exists, md5-check if identical, otherwise rename.
|
||||
If no filename is given, create unique ID.
|
||||
"""
|
||||
x=json.loads(message)
|
||||
url = x['url']
|
||||
eventtype = x['type']
|
||||
|
||||
if eventtype == 'file':
|
||||
filename = x['name']
|
||||
path = nb_dir + u'\\' + x['path'] + u'\\images\\'
|
||||
ensure_dir(path)
|
||||
data = x['data'].split(',') # [0] is header, [1] b64 data
|
||||
png = base64.b64decode(data[1])
|
||||
# check if file exists: skip if identical, rename if new
|
||||
if os.path.exists(path+filename):
|
||||
# print('File %s already exists' % filename)
|
||||
# compare md5sum
|
||||
md5_file = md5sum(path+filename)
|
||||
d = hashlib.md5()
|
||||
d.update(png)
|
||||
md5_websocket = d.hexdigest()
|
||||
if md5_file != md5_websocket:
|
||||
i = 0
|
||||
while True:
|
||||
if not os.path.exists('%s%0d_%s' % (path, i, filename)):
|
||||
break
|
||||
filename = '%0d_%s' % (i, filename)
|
||||
f = open(path+filename, 'wb')
|
||||
f.write(png)
|
||||
f.close()
|
||||
else:
|
||||
f = open(path+filename, 'wb')
|
||||
f.write(png)
|
||||
f.close()
|
||||
status = "OK"
|
||||
#reply = {"status": status, "name": 'images/' + filename }
|
||||
# send url instead of file path, otherwise it won't work for nbconvert
|
||||
url_path = url + '/notebooks' + x['path'] + '/images/' + filename
|
||||
reply = {"status": status, "name": url_path}
|
||||
self.write_message(reply)
|
||||
else:
|
||||
# just reply already existing url
|
||||
status = "OK"
|
||||
reply = {"status": status, "name": url }
|
||||
self.write_message(reply)
|
||||
|
||||
application = tornado.web.Application([
|
||||
(r"/websocket", WebSocketHandler),
|
||||
])
|
||||
|
||||
|
||||
def websocket_server(webport, nbdir):
|
||||
global nb_dir
|
||||
nb_dir = nbdir
|
||||
ioloop.install()
|
||||
try:
|
||||
application.listen(webport)
|
||||
except:
|
||||
# print('Port %d already in use!' % webport)
|
||||
sys.exit(2)
|
||||
main_loop = tornado.ioloop.IOLoop.instance()
|
||||
main_loop.start()
|
||||
|
||||
|
||||
def start_server(webport,nb_dir):
|
||||
print('webport is %s' % webport)
|
||||
print('notebook directory is %s' % nb_dir)
|
||||
|
||||
if webport < 1000 or webport > 65535:
|
||||
print('Illegal webport adress %d' % webport)
|
||||
sys.exit(2)
|
||||
|
||||
if not os.path.exists(nb_dir):
|
||||
print('Directory %s does not exist' % nb_dir)
|
||||
sys.exit(2)
|
||||
|
||||
p = Process(target=websocket_server, args=(webport,nb_dir))
|
||||
p.start()
|
||||
Reference in New Issue
Block a user