{ "metadata": { "cell_tags": [ [ "", 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($('')\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($('')\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": [ "" ] } ], "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": {} } ] }