Skip to content

Instantly share code, notes, and snippets.

@jdfreder
Last active December 25, 2015 04:59
Show Gist options
  • Save jdfreder/6921696 to your computer and use it in GitHub Desktop.
Save jdfreder/6921696 to your computer and use it in GitHub Desktop.
Minimalist example for backbone.js widget PR.
Display the source blob
Display the rendered blob
Raw
{
"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