diff --git a/examples/widgets/Export As (nbconvert).ipynb b/examples/widgets/Export As (nbconvert).ipynb index 3f2061b..561a002 100644 --- a/examples/widgets/Export As (nbconvert).ipynb +++ b/examples/widgets/Export As (nbconvert).ipynb @@ -11,8 +11,12 @@ "cell_type": "code", "collapsed": false, "input": [ + "# Widget related imports\n", "from IPython.html import widgets\n", - "from IPython.display import display, Javascript, clear_output\n", + "from IPython.display import display, clear_output, Javascript\n", + "from IPython.utils.traitlets import Unicode\n", + "\n", + "# nbconvert related imports\n", "from IPython.nbconvert import get_export_names, export_by_name\n", "from IPython.nbconvert.writers import FilesWriter\n", "from IPython.nbformat import current" @@ -26,15 +30,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Create and *display* a StringWidget without a view. The StringWidget will be used to store the notebook name which is otherwise only available in the front-end." + "Create a textbox Widget without displaying it. The widget will be used to store the notebook's name which is otherwise only available in the front-end." ] }, { "cell_type": "code", "collapsed": false, "input": [ - "notebook_name = widgets.StringWidget(default_view_name='')\n", - "display(notebook_name)" + "notebook_name = widgets.TextBoxWidget()" ], "language": "python", "metadata": {}, @@ -52,9 +55,9 @@ "cell_type": "code", "collapsed": false, "input": [ - "js = \"\"\"var model = IPython.notebook.kernel.comm_manager.comms['{comm_id}'].model;\n", + "js = \"\"\"var model = IPython.notebook.kernel.widget_manager.get_model('{model_id}');\n", "model.set('value', IPython.notebook.notebook_name);\n", - "model.save();\"\"\".format(comm_id=notebook_name._comm.comm_id)\n", + "model.save();\"\"\".format(model_id=notebook_name.model_id)\n", "display(Javascript(data=js))" ], "language": "python", @@ -62,14 +65,14 @@ "outputs": [ { "javascript": [ - "var model = IPython.notebook.kernel.comm_manager.comms['af0fadc224134034af6141995abf625a'].model;\n", + "var model = IPython.notebook.kernel.widget_manager.get_model('8c6583524eb3422c99491730a3e1ce6c');\n", "model.set('value', IPython.notebook.notebook_name);\n", "model.save();" ], "metadata": {}, "output_type": "display_data", "text": [ - "" + "" ] } ], @@ -107,17 +110,9 @@ "cell_type": "code", "collapsed": false, "input": [ - "container = widgets.ContainerWidget()\n", - "container.vbox()\n", - "container.align_center()\n", - "\n", - "options = widgets.ContainerWidget(parent=container)\n", - "options.hbox()\n", - "options.align_center()\n", - "exporter_names = widgets.SelectionWidget(parent=options, values=get_export_names(), value='html')\n", - "export_button = widgets.ButtonWidget(parent=options, description=\"Export\")\n", - "\n", - "download_link = widgets.StringWidget(parent=container, default_view_name=\"HTMLView\", visible=False)" + "exporter_names = widgets.DropdownWidget(values=get_export_names(), value='html')\n", + "export_button = widgets.ButtonWidget(description=\"Export\")\n", + "download_link = widgets.HTMLWidget(visible=False)" ], "language": "python", "metadata": {}, @@ -154,17 +149,8 @@ " write_results = file_writer.write(output, resources, notebook_name=notebook_name)\n", " \n", " download_link.value = \"
Results: \\\"{filename}\\\"\".format(filename=write_results)\n", - " download_link.visible = True" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 6 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ + " download_link.visible = True\n", + " \n", "def handle_export():\n", " with open(filename, 'r') as f:\n", " export(filename, current.read(f, 'json'))\n", @@ -173,19 +159,25 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 7 + "prompt_number": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the controls." + ] }, { "cell_type": "code", "collapsed": false, "input": [ - "download_link.visible = False\n", - "display(container)" + "display(exporter_names, export_button, download_link)" ], "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 8 + "prompt_number": 7 } ], "metadata": {} diff --git a/examples/widgets/File Upload Widget.ipynb b/examples/widgets/File Upload Widget.ipynb index 370e579..f78302e 100644 --- a/examples/widgets/File Upload Widget.ipynb +++ b/examples/widgets/File Upload Widget.ipynb @@ -17,11 +17,10 @@ "cell_type": "code", "collapsed": false, "input": [ - "from __future__ import print_function # py 2.7 compat\n", - "\n", "import base64\n", - "from IPython.html import widgets # Widget definitions\n", - "from IPython.display import display # Used to display widgets in the notebook" + "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": {}, @@ -29,31 +28,44 @@ "prompt_number": 1 }, { - "cell_type": "heading", - "level": 1, + "cell_type": "markdown", "metadata": {}, "source": [ - "Custom Widget" + "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": [ - "# Import the base Widget class and the traitlets Unicode class.\n", - "from IPython.html.widgets import Widget\n", - "from IPython.utils.traitlets import Unicode, Int\n", - "\n", - "# Define our FileWidget and its target model and default view.\n", - "class FileWidget(Widget):\n", - " target_name = Unicode('FileWidgetModel')\n", - " default_view_name = Unicode('FilePickerView')\n", + "class FileWidget(widgets.DOMWidget):\n", + " _view_name = Unicode('FilePickerView', sync=True)\n", + " value = Unicode(sync=True)\n", + " filename = Unicode(sync=True)\n", " \n", - " # Define the custom state properties to sync with the front-end\n", - " _keys = ['value', 'filename']\n", - " value = Unicode('')\n", - " filename = Unicode('')\n", - " on_failed = Int(0)" + " 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": {}, @@ -66,46 +78,50 @@ "input": [ "%%javascript\n", "\n", - "require([\"notebook/js/widget\"], function(){\n", - " \n", - " // Define the FileModel and register it with the widget manager.\n", - " var FileModel = IPython.WidgetModel.extend({});\n", - " IPython.widget_manager.register_widget_model('FileWidgetModel', FileModel);\n", - " \n", - " // Define the FilePickerView\n", + "require([\"notebook/js/widgets/widget\"], function(WidgetManager){\n", + "\n", " var FilePickerView = IPython.WidgetView.extend({\n", - " \n", " render: function(){\n", - " var that = this;\n", - " this.$el = $('')\n", - " .attr('type', 'file')\n", - " .change(function(evt){ that.handleFileChange(evt) });\n", + " // Render the view.\n", + " this.setElement($('')\n", + " .attr('type', 'file'));\n", " },\n", " \n", - " // Handles: User input\n", - " handleFileChange: function(evt) { \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 that = this;\n", - " var f = evt.target.files[0];\n", - " if (f) {\n", - " var r = new FileReader();\n", - " r.onload = function(e) {\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.model.update_other_views(that);\n", + " that.touch();\n", " }\n", - " r.readAsText(f);\n", + " file_reader.readAsText(file);\n", " } else {\n", - " this.model.set('on_failed', this.model.get('on_failed') + 1);\n", - " this.model.update_other_views(this);\n", + "\n", + " // The file couldn't be opened. Send an error msg to the\n", + " // back-end.\n", + " this.send({ 'event': 'error' });\n", " }\n", - " this.model.set('filename', f.name);\n", - " this.model.update_other_views(this);\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", - " IPython.widget_manager.register_widget_view('FilePickerView', FilePickerView);\n", + " WidgetManager.register_widget_view('FilePickerView', FilePickerView);\n", "});" ], "language": "python", @@ -114,63 +130,66 @@ { "javascript": [ "\n", - "require([\"notebook/js/widget\"], function(){\n", - " \n", - " // Define the FileModel and register it with the widget manager.\n", - " var FileModel = IPython.WidgetModel.extend({});\n", - " IPython.widget_manager.register_widget_model('FileWidgetModel', FileModel);\n", - " \n", - " // Define the FilePickerView\n", + "require([\"notebook/js/widgets/widget\"], function(WidgetManager){\n", + "\n", " var FilePickerView = IPython.WidgetView.extend({\n", - " \n", " render: function(){\n", - " var that = this;\n", - " this.$el = $('')\n", - " .attr('type', 'file')\n", - " .change(function(evt){ that.handleFileChange(evt) });\n", + " // Render the view.\n", + " this.setElement($('')\n", + " .attr('type', 'file'));\n", " },\n", " \n", - " // Handles: User input\n", - " handleFileChange: function(evt) { \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 that = this;\n", - " var f = evt.target.files[0];\n", - " if (f) {\n", - " var r = new FileReader();\n", - " r.onload = function(e) {\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.model.update_other_views(that);\n", + " that.touch();\n", " }\n", - " r.readAsText(f);\n", + " file_reader.readAsText(file);\n", " } else {\n", - " this.model.set('on_failed', this.model.get('on_failed') + 1);\n", - " this.model.update_other_views(this);\n", + "\n", + " // The file couldn't be opened. Send an error msg to the\n", + " // back-end.\n", + " this.send({ 'event': 'error' });\n", " }\n", - " this.model.set('filename', f.name);\n", - " this.model.update_other_views(this);\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", - " IPython.widget_manager.register_widget_view('FilePickerView', FilePickerView);\n", + " WidgetManager.register_widget_view('FilePickerView', FilePickerView);\n", "});" ], "metadata": {}, "output_type": "display_data", "text": [ - "" + "" ] } ], "prompt_number": 3 }, { - "cell_type": "heading", - "level": 1, + "cell_type": "markdown", "metadata": {}, "source": [ - "Usage" + "The following shows how the file widget can be used." ] }, { @@ -178,22 +197,28 @@ "collapsed": false, "input": [ "file_widget = FileWidget()\n", - "display(file_widget)\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", - "def file_failed(name, old_value, new_value):\n", - " if new_value > old_value:\n", - " print(\"Could not load file contents of %s\" % file_widget.filename)\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.on_trait_change(file_loading, 'filename')\n", - "file_widget.on_trait_change(file_loaded, 'value')\n", - "file_widget.on_trait_change(file_failed, 'on_failed')" + "file_widget" ], "language": "python", "metadata": {}, diff --git a/examples/widgets/Nonblocking Console.ipynb b/examples/widgets/Nonblocking Console.ipynb index d7b0574..492b3c9 100644 --- a/examples/widgets/Nonblocking Console.ipynb +++ b/examples/widgets/Nonblocking Console.ipynb @@ -11,61 +11,20 @@ "cell_type": "code", "collapsed": false, "input": [ + "# Console related imports.\n", "from subprocess import Popen, PIPE\n", "import fcntl\n", "import os\n", + "from IPython.utils.py3compat import bytes_to_str, string_types\n", "\n", + "# Widget related imports.\n", "from IPython.html import widgets\n", - "from IPython.display import display\n", - "from IPython.utils.py3compat import bytes_to_str, string_types" + "from IPython.display import display" ], "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create the output, input, and console toggle widgets." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "console_container = widgets.ContainerWidget(visible=False)\n", - "console_container.set_css('padding', '10px')\n", - "\n", - "console_style = {\n", - " 'font-family': 'monospace',\n", - " 'color': '#AAAAAA',\n", - " 'background': 'black',\n", - " 'width': '800px',\n", - "}\n", - "\n", - "output_box = widgets.StringWidget(parent=console_container, default_view_name='TextAreaView')\n", - "output_box.set_css(console_style)\n", - "output_box.set_css('height', '400px')\n", - "\n", - "input_box = widgets.StringWidget(parent=console_container)\n", - "input_box.set_css(console_style)\n", - "\n", - "toggle_button = widgets.ButtonWidget(description=\"Start Console\")\n", - "def toggle_console():\n", - " console_container.visible = not console_container.visible\n", - " if console_container.visible:\n", - " toggle_button.description=\"Stop Console\"\n", - " input_box.disabled = False\n", - " else:\n", - " toggle_button.description=\"Start Console\"\n", - "toggle_button.on_click(toggle_console)\n" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 2 + "prompt_number": 6 }, { "cell_type": "markdown", @@ -154,7 +113,42 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 3 + "prompt_number": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the console widgets without displaying them." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "console_container = widgets.ContainerWidget(visible=False)\n", + "console_container.set_css('padding', '10px')\n", + "\n", + "console_style = {\n", + " 'font-family': 'monospace',\n", + " 'color': '#AAAAAA',\n", + " 'background': 'black',\n", + " 'width': '800px',\n", + "}\n", + "\n", + "output_box = widgets.TextAreaWidget()\n", + "output_box.set_css(console_style)\n", + "output_box.set_css('height', '400px')\n", + "\n", + "input_box = widgets.TextBoxWidget()\n", + "input_box.set_css(console_style)\n", + "\n", + "console_container.children = [output_box, input_box]" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 8 }, { "cell_type": "markdown", @@ -195,26 +189,36 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 4 + "prompt_number": 9 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Show the console" + "Create the button that will be used to display and hide the console. Display both the console container and the new button used to toggle it." ] }, { "cell_type": "code", "collapsed": false, "input": [ + "toggle_button = widgets.ButtonWidget(description=\"Start Console\")\n", + "def toggle_console():\n", + " console_container.visible = not console_container.visible\n", + " if console_container.visible:\n", + " toggle_button.description=\"Stop Console\"\n", + " input_box.disabled = False\n", + " else:\n", + " toggle_button.description=\"Start Console\"\n", + "toggle_button.on_click(toggle_console)\n", + "\n", "display(toggle_button)\n", "display(console_container)" ], "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 5 + "prompt_number": 10 } ], "metadata": {} diff --git a/examples/widgets/index.ipynb b/examples/widgets/index.ipynb index 13d545b..2a8a487 100644 --- a/examples/widgets/index.ipynb +++ b/examples/widgets/index.ipynb @@ -59,8 +59,7 @@ "- [Export As (nbconvert)](Export As (nbconvert%29.ipynb) \n", "- [Nonblocking Console](Nonblocking Console.ipynb) \n", "- [D3](D3.ipynb) \n", - "- [File Upload Widget](File Upload Widget.ipynb) \n", - "- [Dialogs](Dialogs.ipynb) " + "- [File Upload Widget](File Upload Widget.ipynb) " ] } ],