From 5e538234f6d85890f06d20bf5c2e9a13047dd101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ju=CC=88rgen=20Hasch?= Date: Fri, 26 May 2017 19:42:40 +0200 Subject: [PATCH] Update chrome-clipboard to 5.x --- .../chrome-clipboard/chrome-clipboard.yaml | 9 +- .../nbextensions/chrome-clipboard/main.js | 153 ++++++++---------- .../nbextensions/chrome-clipboard/readme.md | 15 +- 3 files changed, 77 insertions(+), 100 deletions(-) diff --git a/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/chrome-clipboard.yaml b/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/chrome-clipboard.yaml index a51e52a6a..84783630c 100644 --- a/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/chrome-clipboard.yaml +++ b/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/chrome-clipboard.yaml @@ -1,7 +1,12 @@ Type: IPython Notebook Extension Name: Chrome Clipboard -Description: This extension allows using the system-wide clipboard to copy cells and images +Description: This extension allows using the system-wide clipboard to paste images into a notebook Link: readme.md Icon: chrome.png Main: main.js -Compatibility: 4.x +Compatibility: 4.x, 5.x +Parameters: +- name: dragdrop.subdirectory + description: Subdirectory to put images to + input_type: string + default: diff --git a/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/main.js b/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/main.js index 21f1e4816..1cfa10e23 100644 --- a/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/main.js +++ b/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/main.js @@ -5,56 +5,83 @@ define([ 'base/js/namespace', 'jquery', 'base/js/utils', + 'services/config', 'base/js/events' -], function(IPython, $, utils, events) { +], function(IPython, $, utils, configmod, events) { "use strict"; if (window.chrome === undefined) return; + var params = { + subdirectory : '', + }; + + var base_url = utils.get_body_data("baseUrl"); + var config = new configmod.ConfigSection('notebook', {base_url: base_url}); + /* http://stackoverflow.com/questions/3231459/create-unique-id-with-javascript */ - function uniqueid() { + function uniqueid(){ // always start with a letter (for DOM friendlyness) - var idstr = String.fromCharCode(Math.floor((Math.random() * 25) + 65)); + 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) { + var ascicode=Math.floor((Math.random()*42)+48); + if (ascicode<58 || ascicode>64){ // exclude all chars between : (58) and @ (64) - idstr += String.fromCharCode(ascicode); + idstr+=String.fromCharCode(ascicode); } - } while (idstr.length < 32); + } while (idstr.length<32); return (idstr); } - var send_to_server = function (name, path, msg) { + var create_dir = function(path) { + var options = {type:'directory'}; + + var data = JSON.stringify({ + ext: options.ext, + type: options.type + }); + + var settings = { + processData : false, + type : "PUT", + data: data, + contentType: 'application/json', + dataType : "json" + }; + utils.promising_ajax(IPython.contents.api_url(path), settings); + }; + + var send_to_server = function(name, msg) { + var path = utils.url_path_join(utils.url_path_split(IPython.notebook.notebook_path)[0], params.subdirectory); if (name == '') { name = uniqueid() + '.' + msg.match(/data:image\/(\S+);/)[1]; - } - var path = path.substring(0, path.lastIndexOf('/')) + '/'; - if (path === '/') path = ''; - var url = '//' + location.host + '/api/contents/' + path + name; + } + create_dir(path); + var url = '//' + location.host + utils.url_path_join(base_url, 'api/contents', path, name); + var img = msg.replace(/(^\S+,)/, ''); // strip header - var data = {'name': name, 'format': 'base64', 'content': img, 'type': 'file'}; + //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, - error : function() {console.log('Data transfer for copy-paste has failed.'); - } + processData : false, + cache : false, + type : "PUT", + dataType : "json", + data : JSON.stringify(data), + headers : {'Content-Type': 'text/plain'}, + async : false, + error : function() {console.log('Data transfer for clipboard paste failed.'); } }; - utils.promising_ajax(url, settings).then( + utils.promising_ajax(url, settings).then( function on_success (data, status, xhr) { var new_cell = IPython.notebook.insert_cell_below('markdown'); - var str = ''; + var str = '![](' + utils.url_path_join(params.subdirectory, name) + ')'; new_cell.set_text(str); new_cell.execute(); }, function on_error (reason) { - console.log('Data transfer for copy-paste has failed.'); + console.log('Data transfer for clipboard paste has failed.'); }); }; @@ -63,6 +90,15 @@ define([ */ var load_ipython_extension = function() { + config.load(); + config.loaded + .then(function () { + $.extend(true, params, config.data.dragdrop); // update params + if (params.subdirectory) { + console.log('subdir:', params.subdirectory) + } + }) + /* * override clipboard 'paste' and insert new cell from json data in clipboard */ @@ -71,27 +107,14 @@ define([ if (cell.mode == "command") { var items = event.clipboardData.items; for (var i = 0; i < items.length; i++) { - if (items[i].type == 'notebook-cell/json') { - event.preventDefault(); - /* json data adds a new notebook cell */ - var data = event.clipboardData.getData('notebook-cell/json').split("\n").filter(Boolean); - for (var i = 0; i < data.length; i++) { - var ix = data.length - 1 - i; - var new_cell_data = JSON.parse(data[ix]); - var new_cell = IPython.notebook.insert_cell_below(new_cell_data.cell_type); - new_cell.fromJSON(new_cell_data); - if (new_cell.cell_type === "markdown") { - new_cell.execute(); - }; - } - } else if (items[i].type.indexOf('image/') !== -1) { + if (items[i].type.indexOf('image/') !== -1) { event.preventDefault(); /* 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); + send_to_server(filename, evt.target.result); event.preventDefault(); } ); reader.readAsDataURL(blob); @@ -99,56 +122,6 @@ define([ } } }); - - /* - * 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 json = ""; - var text = ""; - var selected_cells = IPython.notebook.get_selected_cells(); - for (var i in selected_cells) { - var j = selected_cells[i].toJSON(); - json += JSON.stringify(j) + '\n'; - text += selected_cells[i].code_mirror.getValue() + '\n'; - } - /* 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: copy marked text */ - event.preventDefault(); - var json = ""; - var text = ""; - var selected_cells = IPython.notebook.get_selected_cells(); - for (var i in selected_cells) { - var j = selected_cells[i].toJSON(); - json += JSON.stringify(j) + '\n'; - text += selected_cells[i].code_mirror.getValue() + '\n'; - IPython.notebook.delete_cell(IPython.notebook.find_cell_index(selected_cells[i])); - } - /* copy cell as json and cell contents as text */ - event.clipboardData.setData('notebook-cell/json', json); - event.clipboardData.setData("Text", text); - } - }); - }; var extension = { diff --git a/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/readme.md b/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/readme.md index 77736a91e..2271aa167 100644 --- a/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/readme.md +++ b/src/jupyter_contrib_nbextensions/nbextensions/chrome-clipboard/readme.md @@ -3,10 +3,7 @@ Chrome Clipboard **Note**: Improved copy&paste functionality is now integrated in the main Jupyter notebook -This notebook extension adds system clipboard actions for single or multiple cells. -It allows cut/copy/paste operation of notebook cells and images. Images will be saved to the directory where the -current notebook sits. There is currently no way to embed images in markdown cells, due to the google-caja sanitizer -used to prevent malicous code execution. Multi-cell operation is possible with the latest Jupyter version, or using the `rubberband` extension in this repository. +This notebook extension adds system clipboard actions pasting images. A demo showing single-cell copy & paste operating in Chrome is available on youtube: [youtu.be/iU9dNe4vMUY](http://youtu.be/iU9dNe4vMUY) @@ -18,12 +15,14 @@ A demo showing single-cell copy & paste operating in Chrome is available on yout Hotkeys: - * `CTRL+C` - Copy cell to system clipboard - * `CTRL+X` - Cut cell and copy to system clipboard - * `CTRL+V` - Paste cell or image from system clipboard + * `CTRL+V` - Paste image from system clipboard +You can specify a target subdirectory using the `dragdrop.subdirectory` + parameter in the notebook configurator. This is the same subdirectory + as used in the `dragdrop` extension. Internals --------- -Regarding copying notebook cells over the clipboard, they are stored as mime-type `notebook-cell/json`. +The image pasted from clipboard will be uploaded to the notebook + directory. A unique ID will be generated as image filename.