Last active
December 25, 2015 04:59
-
-
Save jdfreder/6921696 to your computer and use it in GitHub Desktop.
Minimalist example for backbone.js widget PR.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"metadata": { | |
"name": "" | |
}, | |
"nbformat": 3, | |
"nbformat_minor": 0, | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"from IPython.html.widgets import *\n", | |
"from IPython.display import display\n", | |
"init_widget_js() # Load widget manager" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"javascript": [ | |
"//----------------------------------------------------------------------------\n", | |
"// Copyright (C) 2013 The IPython Development Team\n", | |
"//\n", | |
"// Distributed under the terms of the BSD License. The full license is in\n", | |
"// the file COPYING, distributed as part of this software.\n", | |
"//----------------------------------------------------------------------------\n", | |
"\n", | |
"//============================================================================\n", | |
"// WidgetModel, WidgetView, and WidgetManager\n", | |
"//============================================================================\n", | |
"/**\n", | |
" * Base Widget classes\n", | |
" * @module IPython\n", | |
" * @namespace IPython\n", | |
" * @submodule widget\n", | |
" */\n", | |
"\n", | |
"\n", | |
"// require(['components/underscore/underscore-min.js',\n", | |
"// 'components/backbone/backbone-min.js'],\n", | |
"\n", | |
"\"use strict\";\n", | |
"\n", | |
"// Only run once on a notebook.\n", | |
"if (IPython.notebook.widget_manager == undefined) {\n", | |
"\n", | |
" //-----------------------------------------------------------------------\n", | |
" // WidgetModel class\n", | |
" //-----------------------------------------------------------------------\n", | |
" var WidgetModel = Backbone.Model.extend({\n", | |
" apply: function(sender) {\n", | |
" this.save();\n", | |
"\n", | |
" for (var index in this.views) {\n", | |
" var view = this.views[index];\n", | |
" if (view !== sender) {\n", | |
" view.refresh(); \n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" });\n", | |
"\n", | |
"\n", | |
" //-----------------------------------------------------------------------\n", | |
" // WidgetView class\n", | |
" //-----------------------------------------------------------------------\n", | |
" var WidgetView = Backbone.View.extend({\n", | |
" \n", | |
" initialize: function() {\n", | |
" this.model.on('change',this.refresh,this);\n", | |
" },\n", | |
" \n", | |
" refresh: function() {\n", | |
" this.update();\n", | |
" \n", | |
" if (this.model.css != undefined) {\n", | |
" for (var selector in this.model.css) {\n", | |
" if (this.model.css.hasOwnProperty(selector)) {\n", | |
" \n", | |
" // Get the elements via the css selector. If the selector is\n", | |
" // blank, assume the current element is the target.\n", | |
" var elements = this.$el.find(selector);\n", | |
" if (selector=='') {\n", | |
" elements = this.$el;\n", | |
" }\n", | |
" \n", | |
" // Apply the css traits to all elements that match the selector.\n", | |
" if (elements.length>0){\n", | |
" var css_traits = this.model.css[selector]; \n", | |
" for (var css_key in css_traits) {\n", | |
" if (css_traits.hasOwnProperty(css_key)) {\n", | |
" elements.css(css_key, css_traits[css_key]);\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" },\n", | |
" });\n", | |
"\n", | |
"\n", | |
" //-----------------------------------------------------------------------\n", | |
" // WidgetManager class\n", | |
" //-----------------------------------------------------------------------\n", | |
" // Public constructor\n", | |
" var WidgetManager = function(comm_manager){\n", | |
" this.comm_manager = comm_manager;\n", | |
" this.widget_model_types = {};\n", | |
" this.widget_view_types = {};\n", | |
" this.model_widget_views = {};\n", | |
" \n", | |
" var that = this;\n", | |
" Backbone.sync = function(method, model, options, error) {\n", | |
" var result = that.send_sync(method, model);\n", | |
" if (options.success) {\n", | |
" options.success(result);\n", | |
" }\n", | |
" }; \n", | |
" }\n", | |
"\n", | |
" // Register a widget model type.\n", | |
" WidgetManager.prototype.register_widget_model = function (widget_model_name, widget_model_type) {\n", | |
" \n", | |
" // Register the widget with the comm manager. Make sure to pass this object's context\n", | |
" // in so `this` works in the call back.\n", | |
" this.comm_manager.register_target(widget_model_name, $.proxy(this.handle_com_open, this));\n", | |
" \n", | |
" // Register the types of the model and view correspong to this widget type. Later\n", | |
" // the widget manager will initialize these when the comm is opened.\n", | |
" this.widget_model_types[widget_model_name] = widget_model_type;\n", | |
" }\n", | |
"\n", | |
" // Register a widget view type.\n", | |
" WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {\n", | |
" this.widget_view_types[widget_view_name] = widget_view_type;\n", | |
" }\n", | |
"\n", | |
" // Handle when a comm is opened.\n", | |
" WidgetManager.prototype.handle_com_open = function (comm, msg) {\n", | |
" var widget_type_name = msg.content.target_name;\n", | |
" \n", | |
" // Create the corresponding widget model.\n", | |
" var widget_model = new this.widget_model_types[widget_type_name];\n", | |
"\n", | |
" // Remember comm associated with the model.\n", | |
" widget_model.comm = comm;\n", | |
" comm.model = widget_model;\n", | |
"\n", | |
" // Create an array to remember the views associated with the model.\n", | |
" widget_model.views = [];\n", | |
"\n", | |
" // Add a handle to delete the control when the comm is closed.\n", | |
" var that = this;\n", | |
" var handle_close = function(msg) {\n", | |
" that.handle_comm_closed(comm, msg);\n", | |
" }\n", | |
" comm.on_close(handle_close);\n", | |
"\n", | |
" // Handle incomming messages.\n", | |
" var handle_msg = function(msg) {\n", | |
" that.handle_comm_msg(comm, msg);\n", | |
" }\n", | |
" comm.on_msg(handle_msg);\n", | |
" }\n", | |
"\n", | |
" // Create view that represents the model.\n", | |
" WidgetManager.prototype.show_view = function (widget_area, widget_model, widget_view_name) {\n", | |
" var widget_view = new this.widget_view_types[widget_view_name]({model: widget_model});\n", | |
" widget_view.render();\n", | |
" widget_model.views.push(widget_view);\n", | |
"\n", | |
" // Handle when the view element is remove from the page.\n", | |
" widget_view.$el.on(\"remove\", function(){ \n", | |
" var index = widget_model.views.indexOf(widget_view);\n", | |
" if (index > -1) {\n", | |
" widget_model.views.splice(index, 1);\n", | |
" }\n", | |
" widget_view.remove(); // Clean-up view \n", | |
"\n", | |
" // Close the comm if there are no views left.\n", | |
" if (widget_model.views.length()==0) {\n", | |
" widget_model.comm.close(); \n", | |
" }\n", | |
" });\n", | |
"\n", | |
" // Add the view's element to cell's widget div.\n", | |
" widget_area\n", | |
" .append($(\"<div />\").append(widget_view.$el))\n", | |
" .parent().show(); // Show the widget_area (parent of widget_subarea)\n", | |
"\n", | |
" // Update the view based on the model contents.\n", | |
" widget_view.refresh();\n", | |
" }\n", | |
"\n", | |
" // Handle incomming comm msg.\n", | |
" WidgetManager.prototype.handle_comm_msg = function (comm, msg) {\n", | |
" // Different logic for different methods.\n", | |
" var method = msg.content.data.method;\n", | |
" switch (method){\n", | |
" case 'show':\n", | |
"\n", | |
" // TODO: Get cell from registered output handler.\n", | |
" var cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);\n", | |
" var widget_subarea = cell.element.find('.widget_area').find('.widget_subarea');\n", | |
"\n", | |
" if (msg.content.data.parent != undefined) {\n", | |
" var find_results = widget_subarea.find(\".\" + msg.content.data.parent);\n", | |
" if (find_results.length > 0) {\n", | |
" widget_subarea = find_results;\n", | |
" }\n", | |
" }\n", | |
"\n", | |
" this.show_view(widget_subarea, comm.model, msg.content.data.view_name);\n", | |
" break;\n", | |
" case 'update':\n", | |
" this.handle_update(comm, msg.content.data.state);\n", | |
" break;\n", | |
" }\n", | |
" }\n", | |
"\n", | |
" // Handle when a widget is updated via the python side.\n", | |
" WidgetManager.prototype.handle_update = function (comm, state) {\n", | |
" for (var key in state) {\n", | |
" if (state.hasOwnProperty(key)) {\n", | |
" if (key==\"_css\"){\n", | |
" comm.model.css = state[key];\n", | |
" } else {\n", | |
" comm.model.set(key, state[key]); \n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" comm.model.save();\n", | |
" }\n", | |
"\n", | |
" // Handle when a widget is closed.\n", | |
" WidgetManager.prototype.handle_comm_closed = function (comm, msg) {\n", | |
" for (var view_index in comm.model.views) {\n", | |
" var view = comm.model.views[view_index];\n", | |
" view.remove();\n", | |
" }\n", | |
" }\n", | |
"\n", | |
" // Get the cell output area corresponding to the comm.\n", | |
" WidgetManager.prototype._get_comm_outputarea = function (comm) {\n", | |
" // TODO: get element from comm instead of guessing\n", | |
" var cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index())\n", | |
" return cell.output_area;\n", | |
" }\n", | |
"\n", | |
" // Send widget state to python backend.\n", | |
" WidgetManager.prototype.send_sync = function (method, model) {\n", | |
" \n", | |
" // Create a callback for the output if the widget has an output area associate with it.\n", | |
" var callbacks = {};\n", | |
" var comm = model.comm;\n", | |
" var outputarea = this._get_comm_outputarea(comm);\n", | |
" if (outputarea != null) {\n", | |
" callbacks = {\n", | |
" iopub : {\n", | |
" output : $.proxy(outputarea.handle_output, outputarea),\n", | |
" clear_output : $.proxy(outputarea.handle_clear_output, outputarea)}\n", | |
" };\n", | |
" };\n", | |
" var model_json = model.toJSON();\n", | |
" var data = {sync_method: method, sync_data: model_json};\n", | |
" comm.send(data, callbacks);\n", | |
" return model_json;\n", | |
" }\n", | |
"\n", | |
" IPython.WidgetManager = WidgetManager;\n", | |
" IPython.WidgetModel = WidgetModel;\n", | |
" IPython.WidgetView = WidgetView;\n", | |
"\n", | |
" IPython.notebook.widget_manager = new WidgetManager(IPython.notebook.kernel.comm_manager); \n", | |
"\n", | |
"}\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1ebfb50>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var FloatSliderView = IPython.WidgetView.extend({\n", | |
" \n", | |
" // Called when view is rendered.\n", | |
" render : function(){\n", | |
" this.$el\n", | |
" .html('')\n", | |
" .addClass(this.model.comm.comm_id);\n", | |
" this.$slider = $('<div />')\n", | |
" .slider({})\n", | |
" .addClass('slider');\n", | |
" \n", | |
" // Put the slider in a container \n", | |
" this.$slider_container = $('<div />')\n", | |
" .css('padding-top', '4px')\n", | |
" .css('padding-bottom', '4px')\n", | |
" .append(this.$slider); \n", | |
" this.$el.append(this.$slider_container);\n", | |
" \n", | |
" // Set defaults.\n", | |
" this.update();\n", | |
" },\n", | |
" \n", | |
" // Handles: Backend -> Frontend Sync\n", | |
" // Frontent -> Frontend Sync\n", | |
" update : function(){\n", | |
" // Slider related keys.\n", | |
" var _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation'];\n", | |
" for (var index in _keys) {\n", | |
" var key = _keys[index];\n", | |
" if (this.model.get(key) != undefined) {\n", | |
" this.$slider.slider(\"option\", key, this.model.get(key));\n", | |
" }\n", | |
" }\n", | |
" },\n", | |
" \n", | |
" // Handles: User input\n", | |
" events: { \"slide\" : \"handleSliderChange\" }, \n", | |
" handleSliderChange: function(e, ui) { \n", | |
" this.model.set('value', ui.value); \n", | |
" this.model.apply(this);\n", | |
" },\n", | |
"});\n", | |
"\n", | |
"IPython.notebook.widget_manager.register_widget_view('FloatSliderView', FloatSliderView);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"\n", | |
"var FloatTextView = IPython.WidgetView.extend({\n", | |
" \n", | |
" // Called when view is rendered.\n", | |
" render : function(){\n", | |
" this.$el\n", | |
" .html('')\n", | |
" .addClass(this.model.comm.comm_id);\n", | |
" this.$textbox = $('<input type=\"text\" />')\n", | |
" .addClass('input')\n", | |
" .appendTo(this.$el);\n", | |
" this.update(); // Set defaults.\n", | |
" },\n", | |
" \n", | |
" // Handles: Backend -> Frontend Sync\n", | |
" // Frontent -> Frontend Sync\n", | |
" update : function(){\n", | |
" var value = this.model.get('value');\n", | |
" if (!this.changing && parseFloat(this.$textbox.val()) != value) {\n", | |
" this.$textbox.val(value);\n", | |
" }\n", | |
" \n", | |
" if (this.model.get('disabled')) {\n", | |
" this.$textbox.attr('disabled','disabled');\n", | |
" } else {\n", | |
" this.$textbox.removeAttr('disabled');\n", | |
" }\n", | |
" },\n", | |
" \n", | |
" \n", | |
" events: {\"keyup input\" : \"handleChanging\",\n", | |
" \"paste input\" : \"handleChanging\",\n", | |
" \"cut input\" : \"handleChanging\",\n", | |
" \"change input\" : \"handleChanged\"}, // Fires only when control is validated or looses focus.\n", | |
" \n", | |
" // Handles and validates user input.\n", | |
" handleChanging: function(e) { \n", | |
" \n", | |
" // Try to parse value as a float.\n", | |
" var numericalValue = 0.0;\n", | |
" if (e.target.value != '') {\n", | |
" numericalValue = parseFloat(e.target.value);\n", | |
" }\n", | |
" \n", | |
" // If parse failed, reset value to value stored in model.\n", | |
" if (isNaN(numericalValue)) {\n", | |
" e.target.value = this.model.get('value');\n", | |
" } else if (!isNaN(numericalValue)) {\n", | |
" numericalValue = Math.min(this.model.get('max'), numericalValue);\n", | |
" numericalValue = Math.max(this.model.get('min'), numericalValue);\n", | |
" \n", | |
" // Apply the value if it has changed.\n", | |
" if (numericalValue != this.model.get('value')) {\n", | |
" this.changing = true;\n", | |
" this.model.set('value', numericalValue);\n", | |
" this.model.apply(this);\n", | |
" this.changing = false;\n", | |
" }\n", | |
" }\n", | |
" },\n", | |
" \n", | |
" // Applies validated input.\n", | |
" handleChanged: function(e) { \n", | |
" // Update the textbox\n", | |
" if (this.model.get('value') != e.target.value) {\n", | |
" e.target.value = this.model.get('value');\n", | |
" }\n", | |
" }\n", | |
"});\n", | |
"\n", | |
"IPython.notebook.widget_manager.register_widget_view('FloatTextView', FloatTextView);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var FloatRangeWidgetModel = IPython.WidgetModel.extend({});\n", | |
"IPython.notebook.widget_manager.register_widget_model('FloatRangeWidgetModel', FloatRangeWidgetModel);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var ContainerView = IPython.WidgetView.extend({\n", | |
" \n", | |
" render : function(){\n", | |
" this.$el.html('');\n", | |
" this.$container = $('<div />')\n", | |
" .addClass('container')\n", | |
" .addClass(this.model.comm.comm_id);\n", | |
" this.$el.append(this.$container);\n", | |
" },\n", | |
" \n", | |
" update : function(){},\n", | |
"});\n", | |
"\n", | |
"IPython.notebook.widget_manager.register_widget_view('ContainerView', ContainerView);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var ContainerModel = IPython.WidgetModel.extend({});\n", | |
"IPython.notebook.widget_manager.register_widget_model('container_widget', ContainerModel);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var IntSliderView = IPython.WidgetView.extend({\n", | |
" \n", | |
" // Called when view is rendered.\n", | |
" render : function(){\n", | |
" this.$el.html('');\n", | |
" this.$slider = $('<div />')\n", | |
" .slider({})\n", | |
" .addClass('slider');\n", | |
" \n", | |
" // Put the slider in a container \n", | |
" this.$slider_container = $('<div />')\n", | |
" .css('padding-top', '4px')\n", | |
" .css('padding-bottom', '4px')\n", | |
" .addClass(this.model.comm.comm_id)\n", | |
" .append(this.$slider); \n", | |
" this.$el.append(this.$slider_container);\n", | |
" \n", | |
" // Set defaults.\n", | |
" this.update();\n", | |
" },\n", | |
" \n", | |
" // Handles: Backend -> Frontend Sync\n", | |
" // Frontent -> Frontend Sync\n", | |
" update : function(){\n", | |
" // Slider related keys.\n", | |
" var _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation'];\n", | |
" for (var index in _keys) {\n", | |
" var key = _keys[index];\n", | |
" if (this.model.get(key) != undefined) {\n", | |
" this.$slider.slider(\"option\", key, this.model.get(key));\n", | |
" }\n", | |
" }\n", | |
" },\n", | |
" \n", | |
" // Handles: User input\n", | |
" events: { \"slide\" : \"handleSliderChange\" }, \n", | |
" handleSliderChange: function(e, ui) { \n", | |
" this.model.set('value', ~~ui.value); // Double bit-wise not to truncate decimel\n", | |
" this.model.apply(this);\n", | |
" },\n", | |
"});\n", | |
"\n", | |
"IPython.notebook.widget_manager.register_widget_view('IntSliderView', IntSliderView);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var IntTextView = IPython.WidgetView.extend({\n", | |
" \n", | |
" // Called when view is rendered.\n", | |
" render : function(){\n", | |
" this.$el\n", | |
" .html('')\n", | |
" .addClass(this.model.comm.comm_id);\n", | |
" this.$textbox = $('<input type=\"text\" />')\n", | |
" .addClass('input')\n", | |
" .appendTo(this.$el);\n", | |
" this.update(); // Set defaults.\n", | |
" },\n", | |
" \n", | |
" // Handles: Backend -> Frontend Sync\n", | |
" // Frontent -> Frontend Sync\n", | |
" update : function(){\n", | |
" var value = this.model.get('value');\n", | |
" if (!this.changing && parseInt(this.$textbox.val()) != value) {\n", | |
" this.$textbox.val(value);\n", | |
" }\n", | |
" \n", | |
" if (this.model.get('disabled')) {\n", | |
" this.$textbox.attr('disabled','disabled');\n", | |
" } else {\n", | |
" this.$textbox.removeAttr('disabled');\n", | |
" }\n", | |
" },\n", | |
" \n", | |
" \n", | |
" events: {\"keyup input\" : \"handleChanging\",\n", | |
" \"paste input\" : \"handleChanging\",\n", | |
" \"cut input\" : \"handleChanging\",\n", | |
" \"change input\" : \"handleChanged\"}, // Fires only when control is validated or looses focus.\n", | |
" \n", | |
" // Handles and validates user input.\n", | |
" handleChanging: function(e) { \n", | |
" \n", | |
" // Try to parse value as a float.\n", | |
" var numericalValue = 0;\n", | |
" if (e.target.value != '') {\n", | |
" numericalValue = parseInt(e.target.value);\n", | |
" }\n", | |
" \n", | |
" // If parse failed, reset value to value stored in model.\n", | |
" if (isNaN(numericalValue)) {\n", | |
" e.target.value = this.model.get('value');\n", | |
" } else if (!isNaN(numericalValue)) {\n", | |
" numericalValue = Math.min(this.model.get('max'), numericalValue);\n", | |
" numericalValue = Math.max(this.model.get('min'), numericalValue);\n", | |
" \n", | |
" // Apply the value if it has changed.\n", | |
" if (numericalValue != this.model.get('value')) {\n", | |
" this.changing = true;\n", | |
" this.model.set('value', numericalValue);\n", | |
" this.model.apply(this);\n", | |
" this.changing = false;\n", | |
" }\n", | |
" }\n", | |
" },\n", | |
" \n", | |
" // Applies validated input.\n", | |
" handleChanged: function(e) { \n", | |
" // Update the textbox\n", | |
" if (this.model.get('value') != e.target.value) {\n", | |
" e.target.value = this.model.get('value');\n", | |
" }\n", | |
" }\n", | |
"});\n", | |
"\n", | |
"IPython.notebook.widget_manager.register_widget_view('IntTextView', IntTextView);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var IntRangeWidgetModel = IPython.WidgetModel.extend({});\n", | |
"IPython.notebook.widget_manager.register_widget_model('IntRangeWidgetModel', IntRangeWidgetModel);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var TextareaView = IPython.WidgetView.extend({\n", | |
" \n", | |
" // Called when view is rendered.\n", | |
" render : function(){\n", | |
" this.$el\n", | |
" .html('')\n", | |
" .addClass(this.model.comm.comm_id);\n", | |
" this.$textbox = $('<textarea />')\n", | |
" .attr('rows', 5)\n", | |
" .appendTo(this.$el);\n", | |
" this.update(); // Set defaults.\n", | |
" },\n", | |
" \n", | |
" // Handles: Backend -> Frontend Sync\n", | |
" // Frontent -> Frontend Sync\n", | |
" update : function(){\n", | |
" if (!this.user_invoked_update) {\n", | |
" this.$textbox.val(this.model.get('value'));\n", | |
" }\n", | |
" },\n", | |
" \n", | |
" events: {\"keyup textarea\" : \"handleChanging\",\n", | |
" \"paste textarea\" : \"handleChanging\",\n", | |
" \"cut textarea\" : \"handleChanging\"},\n", | |
" \n", | |
" // Handles and validates user input.\n", | |
" handleChanging: function(e) { \n", | |
" this.user_invoked_update = true;\n", | |
" this.model.set('value', e.target.value);\n", | |
" this.model.apply(this);\n", | |
" this.user_invoked_update = false;\n", | |
" },\n", | |
"});\n", | |
"\n", | |
"IPython.notebook.widget_manager.register_widget_view('TextareaView', TextareaView);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var StringWidgetModel = IPython.WidgetModel.extend({});\n", | |
"IPython.notebook.widget_manager.register_widget_model('StringWidgetModel', StringWidgetModel);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var TextboxView = IPython.WidgetView.extend({\n", | |
" \n", | |
" // Called when view is rendered.\n", | |
" render : function(){\n", | |
" this.$el\n", | |
" .html('')\n", | |
" .addClass(this.model.comm.comm_id);\n", | |
" this.$textbox = $('<input type=\"text\" />')\n", | |
" .addClass('input')\n", | |
" .appendTo(this.$el);\n", | |
" this.update(); // Set defaults.\n", | |
" },\n", | |
" \n", | |
" // Handles: Backend -> Frontend Sync\n", | |
" // Frontent -> Frontend Sync\n", | |
" update : function(){\n", | |
" if (!this.user_invoked_update) {\n", | |
" this.$textbox.val(this.model.get('value'));\n", | |
" }\n", | |
" },\n", | |
" \n", | |
" events: {\"keyup input\" : \"handleChanging\",\n", | |
" \"paste input\" : \"handleChanging\",\n", | |
" \"cut input\" : \"handleChanging\"},\n", | |
" \n", | |
" // Handles and validates user input.\n", | |
" handleChanging: function(e) { \n", | |
" this.user_invoked_update = true;\n", | |
" this.model.set('value', e.target.value);\n", | |
" this.model.apply(this);\n", | |
" this.user_invoked_update = false;\n", | |
" },\n", | |
"});\n", | |
"\n", | |
"IPython.notebook.widget_manager.register_widget_view('TextboxView', TextboxView);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var DropdownView = IPython.WidgetView.extend({\n", | |
" \n", | |
" // Called when view is rendered.\n", | |
" render : function(){\n", | |
" \n", | |
" this.$el\n", | |
" .html('')\n", | |
" .addClass(this.model.comm.comm_id);\n", | |
" this.$buttongroup = $('<div />')\n", | |
" .addClass('btn-group')\n", | |
" .appendTo(this.$el);\n", | |
" this.$droplabel = $('<button />')\n", | |
" .addClass('btn')\n", | |
" .appendTo(this.$buttongroup);\n", | |
" this.$dropbutton = $('<button />')\n", | |
" .addClass('btn')\n", | |
" .addClass('dropdown-toggle')\n", | |
" .attr('data-toggle', 'dropdown')\n", | |
" .html('<span class=\"caret\"></span>')\n", | |
" .appendTo(this.$buttongroup);\n", | |
" this.$droplist = $('<ul />')\n", | |
" .addClass('dropdown-menu')\n", | |
" .appendTo(this.$buttongroup);\n", | |
" \n", | |
" // Set defaults.\n", | |
" this.update();\n", | |
" },\n", | |
" \n", | |
" // Handles: Backend -> Frontend Sync\n", | |
" // Frontent -> Frontend Sync\n", | |
" update : function(){\n", | |
" this.$droplabel.html(this.model.get('value'));\n", | |
" \n", | |
" var items = this.model.get('values');\n", | |
" this.$droplist.html('');\n", | |
" for (var index in items) {\n", | |
" var that = this;\n", | |
" var item_button = $('<a href=\"#\"/>')\n", | |
" .html(items[index])\n", | |
" .on('click', function(e){\n", | |
" that.model.set('value', $(e.target).html(), this );\n", | |
" })\n", | |
" \n", | |
" this.$droplist.append($('<li />').append(item_button))\n", | |
" }\n", | |
" \n", | |
" if (this.model.get('disabled')) {\n", | |
" this.$buttongroup.attr('disabled','disabled');\n", | |
" this.$droplabel.attr('disabled','disabled');\n", | |
" this.$dropbutton.attr('disabled','disabled');\n", | |
" this.$droplist.attr('disabled','disabled');\n", | |
" } else {\n", | |
" this.$buttongroup.removeAttr('disabled');\n", | |
" this.$droplabel.removeAttr('disabled');\n", | |
" this.$dropbutton.removeAttr('disabled');\n", | |
" this.$droplist.removeAttr('disabled');\n", | |
" }\n", | |
" },\n", | |
" \n", | |
"});\n", | |
"\n", | |
"IPython.notebook.widget_manager.register_widget_view('DropdownView', DropdownView);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var RadioButtonView = IPython.WidgetView.extend({\n", | |
" \n", | |
" // Called when view is rendered.\n", | |
" render : function(){\n", | |
" this.$el\n", | |
" .html('')\n", | |
" .addClass(this.model.comm.comm_id);\n", | |
" this.update();\n", | |
" },\n", | |
" \n", | |
" // Handles: Backend -> Frontend Sync\n", | |
" // Frontent -> Frontend Sync\n", | |
" update : function(){\n", | |
" \n", | |
" // Add missing items to the DOM.\n", | |
" var items = this.model.get('values');\n", | |
" for (var index in items) {\n", | |
" var item_query = ' :input[value=\"' + items[index] + '\"]';\n", | |
" if (this.$el.find(item_query).length == 0) {\n", | |
" var $label = $('<label />')\n", | |
" .addClass('radio')\n", | |
" .html(items[index])\n", | |
" .appendTo(this.$el);\n", | |
" \n", | |
" var that = this;\n", | |
" $('<input />')\n", | |
" .attr('type', 'radio')\n", | |
" .addClass(this.model)\n", | |
" .val(items[index])\n", | |
" .prependTo($label)\n", | |
" .on('click', function(e){\n", | |
" that.model.set('value', $(e.target).val(), this);\n", | |
" that.model.apply();\n", | |
" });\n", | |
" }\n", | |
" \n", | |
" if (this.model.get('value') == items[index]) {\n", | |
" this.$el.find(item_query).prop('checked', true);\n", | |
" } else {\n", | |
" this.$el.find(item_query).prop('checked', false);\n", | |
" }\n", | |
" }\n", | |
" \n", | |
" // Remove items that no longer exist.\n", | |
" this.$el.find('input').each(function(i, obj) {\n", | |
" var value = $(obj).val();\n", | |
" var found = false;\n", | |
" for (var index in items) {\n", | |
" if (items[index] == value) {\n", | |
" found = true;\n", | |
" break;\n", | |
" }\n", | |
" }\n", | |
" \n", | |
" if (!found) {\n", | |
" $(obj).parent().remove();\n", | |
" }\n", | |
" });\n", | |
" },\n", | |
" \n", | |
"});\n", | |
"\n", | |
"IPython.notebook.widget_manager.register_widget_view('RadioButtonView', RadioButtonView);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
}, | |
{ | |
"javascript": [ | |
"var SelectionWidgetModel = IPython.WidgetModel.extend({});\n", | |
"IPython.notebook.widget_manager.register_widget_model('SelectionWidgetModel', SelectionWidgetModel);\n" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x1e09d90>" | |
] | |
} | |
], | |
"prompt_number": 1 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a = FloatRangeWidget()\n", | |
"display(a)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 2 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"display(a, view_name=\"FloatTextView\")" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 3 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"b = ContainerWidget(_css = {'': {'background': '#00FF00', 'padding': '10px'}}) # WARNING: Setting the internal _css property \n", | |
" # will not be required in the future.\n", | |
"c = SelectionWidget(parent=b, values=['Item A', 'Item B', 'Item C'], value='Select One', default_view_name='RadioButtonView')\n", | |
"display(b)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 4 | |
} | |
], | |
"metadata": {} | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment