You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
8.6 KiB
249 lines
8.6 KiB
{
|
|
"metadata": {
|
|
"cell_tags": [
|
|
[
|
|
"<None>",
|
|
null
|
|
]
|
|
],
|
|
"name": ""
|
|
},
|
|
"nbformat": 3,
|
|
"nbformat_minor": 0,
|
|
"worksheets": [
|
|
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"collapsed": false,
|
|
"input": [
|
|
"import base64\n",
|
|
"from __future__ import print_function # py 2.7 compat.\n",
|
|
"from IPython.html import widgets # Widget definitions.\n",
|
|
"from IPython.utils.traitlets import Unicode # Traitlet needed to add synced attributes to the widget."
|
|
],
|
|
"language": "python",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"prompt_number": 1
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"This is a custom widget that allows the user to upload file data to the notebook server. The file data is sent via a statefull `value` attribute of the widget. The widget has an upload failed event that fires in the front-end and is echoed to the back-end using a custom msg."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"collapsed": false,
|
|
"input": [
|
|
"class FileWidget(widgets.DOMWidget):\n",
|
|
" _view_name = Unicode('FilePickerView', sync=True)\n",
|
|
" value = Unicode(sync=True)\n",
|
|
" filename = Unicode(sync=True)\n",
|
|
" \n",
|
|
" def __init__(self, **kwargs):\n",
|
|
" \"\"\"Constructor\"\"\"\n",
|
|
" widgets.DOMWidget.__init__(self, **kwargs) # Call the base.\n",
|
|
" \n",
|
|
" # Allow the user to register error callbacks with the following signatures:\n",
|
|
" # callback()\n",
|
|
" # callback(sender)\n",
|
|
" self.errors = widgets.CallbackDispatcher(accepted_nargs=[0, 1])\n",
|
|
" \n",
|
|
" # Listen for custom msgs\n",
|
|
" self.on_msg(self._handle_custom_msg)\n",
|
|
"\n",
|
|
" def _handle_custom_msg(self, content):\n",
|
|
" \"\"\"Handle a msg from the front-end.\n",
|
|
"\n",
|
|
" Parameters\n",
|
|
" ----------\n",
|
|
" content: dict\n",
|
|
" Content of the msg.\"\"\"\n",
|
|
" if 'event' in content and content['event'] == 'error':\n",
|
|
" self.errors()\n",
|
|
" self.errors(self)\n",
|
|
" "
|
|
],
|
|
"language": "python",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"prompt_number": 2
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"collapsed": false,
|
|
"input": [
|
|
"%%javascript\n",
|
|
"\n",
|
|
"require([\"widgets/js/widget\"], function(WidgetManager){\n",
|
|
"\n",
|
|
" var FilePickerView = IPython.WidgetView.extend({\n",
|
|
" render: function(){\n",
|
|
" // Render the view.\n",
|
|
" this.setElement($('<input />')\n",
|
|
" .attr('type', 'file'));\n",
|
|
" },\n",
|
|
" \n",
|
|
" events: {\n",
|
|
" // List of events and their handlers.\n",
|
|
" 'change': 'handle_file_change',\n",
|
|
" },\n",
|
|
" \n",
|
|
" handle_file_change: function(evt) { \n",
|
|
" // Handle when the user has changed the file.\n",
|
|
" \n",
|
|
" // Retrieve the first (and only!) File from the FileList object\n",
|
|
" var file = evt.target.files[0];\n",
|
|
" if (file) {\n",
|
|
"\n",
|
|
" // Read the file's textual content and set value to those contents.\n",
|
|
" var that = this;\n",
|
|
" var file_reader = new FileReader();\n",
|
|
" file_reader.onload = function(e) {\n",
|
|
" that.model.set('value', e.target.result);\n",
|
|
" that.touch();\n",
|
|
" }\n",
|
|
" file_reader.readAsText(file);\n",
|
|
" } else {\n",
|
|
"\n",
|
|
" // The file couldn't be opened. Send an error msg to the\n",
|
|
" // back-end.\n",
|
|
" this.send({ 'event': 'error' });\n",
|
|
" }\n",
|
|
"\n",
|
|
" // Set the filename of the file.\n",
|
|
" this.model.set('filename', file.name);\n",
|
|
" this.touch();\n",
|
|
" },\n",
|
|
" });\n",
|
|
" \n",
|
|
" // Register the DatePickerView with the widget manager.\n",
|
|
" WidgetManager.register_widget_view('FilePickerView', FilePickerView);\n",
|
|
"});"
|
|
],
|
|
"language": "python",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"javascript": [
|
|
"\n",
|
|
"require([\"widgets/js/widget\"], function(WidgetManager){\n",
|
|
"\n",
|
|
" var FilePickerView = IPython.WidgetView.extend({\n",
|
|
" render: function(){\n",
|
|
" // Render the view.\n",
|
|
" this.setElement($('<input />')\n",
|
|
" .attr('type', 'file'));\n",
|
|
" },\n",
|
|
" \n",
|
|
" events: {\n",
|
|
" // List of events and their handlers.\n",
|
|
" 'change': 'handle_file_change',\n",
|
|
" },\n",
|
|
" \n",
|
|
" handle_file_change: function(evt) { \n",
|
|
" // Handle when the user has changed the file.\n",
|
|
" \n",
|
|
" // Retrieve the first (and only!) File from the FileList object\n",
|
|
" var file = evt.target.files[0];\n",
|
|
" if (file) {\n",
|
|
"\n",
|
|
" // Read the file's textual content and set value to those contents.\n",
|
|
" var that = this;\n",
|
|
" var file_reader = new FileReader();\n",
|
|
" file_reader.onload = function(e) {\n",
|
|
" that.model.set('value', e.target.result);\n",
|
|
" that.touch();\n",
|
|
" }\n",
|
|
" file_reader.readAsText(file);\n",
|
|
" } else {\n",
|
|
"\n",
|
|
" // The file couldn't be opened. Send an error msg to the\n",
|
|
" // back-end.\n",
|
|
" this.send({ 'event': 'error' });\n",
|
|
" }\n",
|
|
"\n",
|
|
" // Set the filename of the file.\n",
|
|
" this.model.set('filename', file.name);\n",
|
|
" this.touch();\n",
|
|
" },\n",
|
|
" });\n",
|
|
" \n",
|
|
" // Register the DatePickerView with the widget manager.\n",
|
|
" WidgetManager.register_widget_view('FilePickerView', FilePickerView);\n",
|
|
"});"
|
|
],
|
|
"metadata": {},
|
|
"output_type": "display_data",
|
|
"text": [
|
|
"<IPython.core.display.Javascript at 0x36df2d0>"
|
|
]
|
|
}
|
|
],
|
|
"prompt_number": 3
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The following shows how the file widget can be used."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"collapsed": false,
|
|
"input": [
|
|
"file_widget = FileWidget()\n",
|
|
"\n",
|
|
"# Register an event to echo the filename when it has been changed.\n",
|
|
"def file_loading():\n",
|
|
" print(\"Loading %s\" % file_widget.filename)\n",
|
|
"file_widget.on_trait_change(file_loading, 'filename')\n",
|
|
"\n",
|
|
"# Register an event to echo the filename and contents when a file\n",
|
|
"# has been uploaded.\n",
|
|
"def file_loaded():\n",
|
|
" print(\"Loaded, file contents: %s\" % file_widget.value)\n",
|
|
"file_widget.on_trait_change(file_loaded, 'value')\n",
|
|
"\n",
|
|
"# Register an event to print an error message when a file could not\n",
|
|
"# be opened. Since the error messages are not handled through\n",
|
|
"# traitlets but instead handled through custom msgs, the registration\n",
|
|
"# of the handler is different than the two examples above. Instead\n",
|
|
"# the API provided by the CallbackDispatcher must be used.\n",
|
|
"def file_failed():\n",
|
|
" print(\"Could not load file contents of %s\" % file_widget.filename)\n",
|
|
"file_widget.errors.register_callback(file_failed)\n",
|
|
"\n",
|
|
"file_widget"
|
|
],
|
|
"language": "python",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"output_type": "stream",
|
|
"stream": "stdout",
|
|
"text": [
|
|
"Loading test.txt\n"
|
|
]
|
|
},
|
|
{
|
|
"output_type": "stream",
|
|
"stream": "stdout",
|
|
"text": [
|
|
"Loaded, file contents: Hello World!\n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"prompt_number": 4
|
|
}
|
|
],
|
|
"metadata": {}
|
|
}
|
|
]
|
|
}
|