From 84cd0629896b018eb444568e75ab404b49a3ae5c 2014-01-16 10:55:59
From: Jonathan Frederic <jdfreder@calpoly.edu>
Date: 2014-01-16 10:55:59
Subject: [PATCH] Lots of updates to widget(s) js
Use require.js (again)
Allow IntTextView and FloatTextView to be used without min/max

---

diff --git a/IPython/html/static/notebook/js/widget.js b/IPython/html/static/notebook/js/widget.js
index 3a255b6..2cd773e 100644
--- a/IPython/html/static/notebook/js/widget.js
+++ b/IPython/html/static/notebook/js/widget.js
@@ -17,237 +17,245 @@
 
 "use strict";
 
-// Only run once on a notebook.
-if (IPython.notebook.widget_manager == undefined) {
-
-    //-----------------------------------------------------------------------
-    // WidgetModel class
-    //-----------------------------------------------------------------------
-    var WidgetModel = Backbone.Model.extend({
-        apply: function(sender) {
-            this.save();
-
-            for (var index in this.views) {
-                var view = this.views[index];
-                if (view !== sender) {
-                    view.refresh();    
+// Use require.js 'define' method so that require.js is intelligent enough to
+// syncronously load everything within this file when it is being 'required' 
+// elsewhere.
+define(["static/components/underscore/underscore-min.js",
+         "static/components/backbone/backbone-min.js",
+        ], function(){
+
+    // Only run once on a notebook.
+    if (IPython.notebook.widget_manager == undefined) {
+
+        //--------------------------------------------------------------------
+        // WidgetModel class
+        //--------------------------------------------------------------------
+        var WidgetModel = Backbone.Model.extend({
+            apply: function(sender) {
+                this.save();
+
+                for (var index in this.views) {
+                    var view = this.views[index];
+                    if (view !== sender) {
+                        view.refresh();    
+                    }
                 }
             }
-        }
-    });
-
-
-    //-----------------------------------------------------------------------
-    // WidgetView class
-    //-----------------------------------------------------------------------
-    var WidgetView = Backbone.View.extend({
-        
-        initialize: function() {
-            this.model.on('change',this.refresh,this);
-        },
-        
-        refresh: function() {
-            this.update();
+        });
+
+
+        //--------------------------------------------------------------------
+        // WidgetView class
+        //--------------------------------------------------------------------
+        var WidgetView = Backbone.View.extend({
             
-            if (this.model.css != undefined) {
-                for (var selector in this.model.css) {
-                    if (this.model.css.hasOwnProperty(selector)) {
-                        
-                        // Get the elements via the css selector.  If the selector is
-                        // blank, assume the current element is the target.
-                        var elements = this.$el.find(selector);
-                        if (selector=='') {
-                            elements = this.$el;
-                        }
-                        
-                        // Apply the css traits to all elements that match the selector.
-                        if (elements.length>0){
-                            var css_traits = this.model.css[selector];    
-                            for (var css_key in css_traits) {
-                                if (css_traits.hasOwnProperty(css_key)) {
-                                    elements.css(css_key, css_traits[css_key]);
+            initialize: function() {
+                this.model.on('change',this.refresh,this);
+            },
+            
+            refresh: function() {
+                this.update();
+                
+                if (this.model.css != undefined) {
+                    for (var selector in this.model.css) {
+                        if (this.model.css.hasOwnProperty(selector)) {
+                            
+                            // Get the elements via the css selector.  If the selector is
+                            // blank, assume the current element is the target.
+                            var elements = this.$el.find(selector);
+                            if (selector=='') {
+                                elements = this.$el;
+                            }
+                            
+                            // Apply the css traits to all elements that match the selector.
+                            if (elements.length>0){
+                                var css_traits = this.model.css[selector];    
+                                for (var css_key in css_traits) {
+                                    if (css_traits.hasOwnProperty(css_key)) {
+                                        elements.css(css_key, css_traits[css_key]);
+                                    }
                                 }
                             }
                         }
                     }
                 }
-            }
-        },
-    });
-
-
-    //-----------------------------------------------------------------------
-    // WidgetManager class
-    //-----------------------------------------------------------------------
-    // Public constructor
-    var WidgetManager = function(comm_manager){
-        this.comm_manager = comm_manager;
-        this.widget_model_types = {};
-        this.widget_view_types = {};
-        this.model_widget_views = {};
-        
-        var that = this;
-        Backbone.sync = function(method, model, options, error) {
-            var result = that.send_sync(method, model);
-            if (options.success) {
-              options.success(result);
-            }
-        }; 
-    }
-
-    // Register a widget model type.
-    WidgetManager.prototype.register_widget_model = function (widget_model_name, widget_model_type) {
-        
-        // Register the widget with the comm manager.  Make sure to pass this object's context
-        // in so `this` works in the call back.
-        this.comm_manager.register_target(widget_model_name, $.proxy(this.handle_com_open, this));
-        
-        // Register the types of the model and view correspong to this widget type.  Later
-        // the widget manager will initialize these when the comm is opened.
-        this.widget_model_types[widget_model_name] = widget_model_type;
-    }
-
-    // Register a widget view type.
-    WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
-        this.widget_view_types[widget_view_name] = widget_view_type;
-    }
-
-    // Handle when a comm is opened.
-    WidgetManager.prototype.handle_com_open = function (comm, msg) {
-        var widget_type_name = msg.content.target_name;
-        
-        // Create the corresponding widget model.
-        var widget_model = new this.widget_model_types[widget_type_name];
-
-        // Remember comm associated with the model.
-        widget_model.comm = comm;
-        comm.model = widget_model;
-
-        // Create an array to remember the views associated with the model.
-        widget_model.views = [];
-
-        // Add a handle to delete the control when the comm is closed.
-        var that = this;
-        var handle_close = function(msg) {
-            that.handle_comm_closed(comm, msg);
+            },
+        });
+
+
+        //--------------------------------------------------------------------
+        // WidgetManager class
+        //--------------------------------------------------------------------
+        // Public constructor
+        var WidgetManager = function(comm_manager){
+            this.comm_manager = comm_manager;
+            this.widget_model_types = {};
+            this.widget_view_types = {};
+            this.model_widget_views = {};
+            
+            var that = this;
+            Backbone.sync = function(method, model, options, error) {
+                var result = that.send_sync(method, model);
+                if (options.success) {
+                  options.success(result);
+                }
+            }; 
         }
-        comm.on_close(handle_close);
 
-        // Handle incomming messages.
-        var handle_msg = function(msg) {
-            that.handle_comm_msg(comm, msg);
+        // Register a widget model type.
+        WidgetManager.prototype.register_widget_model = function (widget_model_name, widget_model_type) {
+            
+            // Register the widget with the comm manager.  Make sure to pass this object's context
+            // in so `this` works in the call back.
+            this.comm_manager.register_target(widget_model_name, $.proxy(this.handle_com_open, this));
+            
+            // Register the types of the model and view correspong to this widget type.  Later
+            // the widget manager will initialize these when the comm is opened.
+            this.widget_model_types[widget_model_name] = widget_model_type;
         }
-        comm.on_msg(handle_msg);
-    }
-
-    // Create view that represents the model.
-    WidgetManager.prototype.show_view = function (widget_area, widget_model, widget_view_name) {
-        var widget_view = new this.widget_view_types[widget_view_name]({model: widget_model});
-        widget_view.render();
-        widget_model.views.push(widget_view);
-
-        // Handle when the view element is remove from the page.
-        widget_view.$el.on("remove", function(){ 
-            var index = widget_model.views.indexOf(widget_view);
-            if (index > -1) {
-                widget_model.views.splice(index, 1);
+
+        // Register a widget view type.
+        WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
+            this.widget_view_types[widget_view_name] = widget_view_type;
+        }
+
+        // Handle when a comm is opened.
+        WidgetManager.prototype.handle_com_open = function (comm, msg) {
+            var widget_type_name = msg.content.target_name;
+            
+            // Create the corresponding widget model.
+            var widget_model = new this.widget_model_types[widget_type_name];
+
+            // Remember comm associated with the model.
+            widget_model.comm = comm;
+            comm.model = widget_model;
+
+            // Create an array to remember the views associated with the model.
+            widget_model.views = [];
+
+            // Add a handle to delete the control when the comm is closed.
+            var that = this;
+            var handle_close = function(msg) {
+                that.handle_comm_closed(comm, msg);
             }
-            widget_view.remove(); // Clean-up view 
+            comm.on_close(handle_close);
 
-            // Close the comm if there are no views left.
-            if (widget_model.views.length()==0) {
-                widget_model.comm.close();     
+            // Handle incomming messages.
+            var handle_msg = function(msg) {
+                that.handle_comm_msg(comm, msg);
             }
-        });
+            comm.on_msg(handle_msg);
+        }
 
-        // Add the view's element to cell's widget div.
-        widget_area
-            .append($("<div />").append(widget_view.$el))
-            .parent().show(); // Show the widget_area (parent of widget_subarea)
-
-        // Update the view based on the model contents.
-        widget_view.refresh();
-    }
-
-    // Handle incomming comm msg.
-    WidgetManager.prototype.handle_comm_msg = function (comm, msg) {
-        // Different logic for different methods.
-        var method = msg.content.data.method;
-        switch (method){
-            case 'show':
-
-                // TODO: Get cell from registered output handler.
-                var cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);
-                var widget_subarea = cell.element.find('.widget_area').find('.widget_subarea');
-
-                if (msg.content.data.parent != undefined) {
-                    var find_results = widget_subarea.find("." + msg.content.data.parent);
-                    if (find_results.length > 0) {
-                        widget_subarea = find_results;
-                    }
+        // Create view that represents the model.
+        WidgetManager.prototype.show_view = function (widget_area, widget_model, widget_view_name) {
+            var widget_view = new this.widget_view_types[widget_view_name]({model: widget_model});
+            widget_view.render();
+            widget_model.views.push(widget_view);
+
+            // Handle when the view element is remove from the page.
+            widget_view.$el.on("remove", function(){ 
+                var index = widget_model.views.indexOf(widget_view);
+                if (index > -1) {
+                    widget_model.views.splice(index, 1);
+                }
+                widget_view.remove(); // Clean-up view 
+
+                // Close the comm if there are no views left.
+                if (widget_model.views.length()==0) {
+                    widget_model.comm.close();     
                 }
+            });
+
+            // Add the view's element to cell's widget div.
+            widget_area
+                .append($("<div />").append(widget_view.$el))
+                .parent().show(); // Show the widget_area (parent of widget_subarea)
+
+            // Update the view based on the model contents.
+            widget_view.refresh();
+        }
+
+        // Handle incomming comm msg.
+        WidgetManager.prototype.handle_comm_msg = function (comm, msg) {
+            // Different logic for different methods.
+            var method = msg.content.data.method;
+            switch (method){
+                case 'show':
+
+                    // TODO: Get cell from registered output handler.
+                    var cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);
+                    var widget_subarea = cell.element.find('.widget_area').find('.widget_subarea');
+
+                    if (msg.content.data.parent != undefined) {
+                        var find_results = widget_subarea.find("." + msg.content.data.parent);
+                        if (find_results.length > 0) {
+                            widget_subarea = find_results;
+                        }
+                    }
 
-                this.show_view(widget_subarea, comm.model, msg.content.data.view_name);
-                break;
-            case 'update':
-                this.handle_update(comm, msg.content.data.state);
-                break;
+                    this.show_view(widget_subarea, comm.model, msg.content.data.view_name);
+                    break;
+                case 'update':
+                    this.handle_update(comm, msg.content.data.state);
+                    break;
+            }
         }
-    }
-
-    // Handle when a widget is updated via the python side.
-    WidgetManager.prototype.handle_update = function (comm, state) {
-        for (var key in state) {
-            if (state.hasOwnProperty(key)) {
-                if (key=="_css"){
-                    comm.model.css = state[key];
-                } else {
-                    comm.model.set(key, state[key]); 
+
+        // Handle when a widget is updated via the python side.
+        WidgetManager.prototype.handle_update = function (comm, state) {
+            for (var key in state) {
+                if (state.hasOwnProperty(key)) {
+                    if (key=="_css"){
+                        comm.model.css = state[key];
+                    } else {
+                        comm.model.set(key, state[key]); 
+                    }
                 }
             }
+            comm.model.save();
         }
-        comm.model.save();
-    }
-
-    // Handle when a widget is closed.
-    WidgetManager.prototype.handle_comm_closed = function (comm, msg) {
-        for (var view_index in comm.model.views) {
-            var view = comm.model.views[view_index];
-            view.remove();
+
+        // Handle when a widget is closed.
+        WidgetManager.prototype.handle_comm_closed = function (comm, msg) {
+            for (var view_index in comm.model.views) {
+                var view = comm.model.views[view_index];
+                view.remove();
+            }
         }
-    }
-
-    // Get the cell output area corresponding to the comm.
-    WidgetManager.prototype._get_comm_outputarea = function (comm) {
-        // TODO: get element from comm instead of guessing
-        var cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index())
-        return cell.output_area;
-    }
-
-    // Send widget state to python backend.
-    WidgetManager.prototype.send_sync = function (method, model) {
-        
-        // Create a callback for the output if the widget has an output area associate with it.
-        var callbacks = {};
-        var comm = model.comm;
-        var outputarea = this._get_comm_outputarea(comm);
-        if (outputarea != null) {
-            callbacks = {
-                iopub : {
-                output : $.proxy(outputarea.handle_output, outputarea),
-                clear_output : $.proxy(outputarea.handle_clear_output, outputarea)}
+
+        // Get the cell output area corresponding to the comm.
+        WidgetManager.prototype._get_comm_outputarea = function (comm) {
+            // TODO: get element from comm instead of guessing
+            var cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index())
+            return cell.output_area;
+        }
+
+        // Send widget state to python backend.
+        WidgetManager.prototype.send_sync = function (method, model) {
+            
+            // Create a callback for the output if the widget has an output area associate with it.
+            var callbacks = {};
+            var comm = model.comm;
+            var outputarea = this._get_comm_outputarea(comm);
+            if (outputarea != null) {
+                callbacks = {
+                    iopub : {
+                    output : $.proxy(outputarea.handle_output, outputarea),
+                    clear_output : $.proxy(outputarea.handle_clear_output, outputarea)}
+                };
             };
-        };
-        var model_json = model.toJSON();
-        var data = {sync_method: method, sync_data: model_json};
-        comm.send(data, callbacks);
-        return model_json;
-    }
+            var model_json = model.toJSON();
+            var data = {sync_method: method, sync_data: model_json};
+            comm.send(data, callbacks);
+            return model_json;
+        }
 
-    IPython.WidgetManager = WidgetManager;
-    IPython.WidgetModel = WidgetModel;
-    IPython.WidgetView = WidgetView;
+        IPython.WidgetManager = WidgetManager;
+        IPython.WidgetModel = WidgetModel;
+        IPython.WidgetView = WidgetView;
 
-    IPython.notebook.widget_manager = new WidgetManager(IPython.notebook.kernel.comm_manager);    
+        IPython.notebook.widget_manager = new WidgetManager(IPython.notebook.kernel.comm_manager);    
 
-};
+    };
+});
diff --git a/IPython/html/static/notebook/js/widgets/container.js b/IPython/html/static/notebook/js/widgets/container.js
index a4f1325..3de2b5e 100644
--- a/IPython/html/static/notebook/js/widgets/container.js
+++ b/IPython/html/static/notebook/js/widgets/container.js
@@ -1,17 +1,19 @@
-var ContainerModel = IPython.WidgetModel.extend({});
-IPython.notebook.widget_manager.register_widget_model('container_widget', ContainerModel);
+require(["notebook/js/widget"], function(){
+    var ContainerModel = IPython.WidgetModel.extend({});
+    IPython.notebook.widget_manager.register_widget_model('container_widget', ContainerModel);
 
-var ContainerView = IPython.WidgetView.extend({
-    
-    render : function(){
-        this.$el.html('');
-        this.$container = $('<div />')
-            .addClass('container')
-            .addClass(this.model.comm.comm_id);
-        this.$el.append(this.$container);
-    },
-    
-    update : function(){},
-});
+    var ContainerView = IPython.WidgetView.extend({
+        
+        render : function(){
+            this.$el.html('');
+            this.$container = $('<div />')
+                .addClass('container')
+                .addClass(this.model.comm.comm_id);
+            this.$el.append(this.$container);
+        },
+        
+        update : function(){},
+    });
 
-IPython.notebook.widget_manager.register_widget_view('ContainerView', ContainerView);
+    IPython.notebook.widget_manager.register_widget_view('ContainerView', ContainerView);
+});
\ No newline at end of file
diff --git a/IPython/html/static/notebook/js/widgets/float_range.js b/IPython/html/static/notebook/js/widgets/float_range.js
index 0fc5366..d4c0e5b 100644
--- a/IPython/html/static/notebook/js/widgets/float_range.js
+++ b/IPython/html/static/notebook/js/widgets/float_range.js
@@ -1,119 +1,125 @@
-var FloatRangeWidgetModel = IPython.WidgetModel.extend({});
-IPython.notebook.widget_manager.register_widget_model('FloatRangeWidgetModel', FloatRangeWidgetModel);
+require(["notebook/js/widget"], function(){
+    var FloatRangeWidgetModel = IPython.WidgetModel.extend({});
+    IPython.notebook.widget_manager.register_widget_model('FloatRangeWidgetModel', FloatRangeWidgetModel);
 
-var FloatSliderView = IPython.WidgetView.extend({
-    
-    // Called when view is rendered.
-    render : function(){
-        this.$el
-            .html('')
-            .addClass(this.model.comm.comm_id);
-        this.$slider = $('<div />')
-                        .slider({})
-                        .addClass('slider');
+    var FloatSliderView = IPython.WidgetView.extend({
         
-        // Put the slider in a container 
-        this.$slider_container = $('<div />')
-                                .css('padding-top', '4px')
-                                .css('padding-bottom', '4px')
-                                .append(this.$slider);    
-        this.$el.append(this.$slider_container);
+        // Called when view is rendered.
+        render : function(){
+            this.$el
+                .html('')
+                .addClass(this.model.comm.comm_id);
+            this.$slider = $('<div />')
+                            .slider({})
+                            .addClass('slider');
+            
+            // Put the slider in a container 
+            this.$slider_container = $('<div />')
+                                    .css('padding-top', '4px')
+                                    .css('padding-bottom', '4px')
+                                    .append(this.$slider);    
+            this.$el.append(this.$slider_container);
+            
+            // Set defaults.
+            this.update();
+        },
         
-        // Set defaults.
-        this.update();
-    },
-    
-    // Handles: Backend -> Frontend Sync
-    //          Frontent -> Frontend Sync
-    update : function(){
-        // Slider related keys.
-        var _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation'];
-        for (var index in _keys) {
-            var key = _keys[index];
-            if (this.model.get(key) != undefined) {
-                this.$slider.slider("option", key, this.model.get(key));
+        // Handles: Backend -> Frontend Sync
+        //          Frontent -> Frontend Sync
+        update : function(){
+            // Slider related keys.
+            var _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation'];
+            for (var index in _keys) {
+                var key = _keys[index];
+                if (this.model.get(key) != undefined) {
+                    this.$slider.slider("option", key, this.model.get(key));
+                }
             }
-        }
-    },
-    
-    // Handles: User input
-    events: { "slide" : "handleSliderChange" }, 
-    handleSliderChange: function(e, ui) { 
-        this.model.set('value', ui.value); 
-        this.model.apply(this);
-    },
-});
+        },
+        
+        // Handles: User input
+        events: { "slide" : "handleSliderChange" }, 
+        handleSliderChange: function(e, ui) { 
+            this.model.set('value', ui.value); 
+            this.model.apply(this);
+        },
+    });
 
-IPython.notebook.widget_manager.register_widget_view('FloatSliderView', FloatSliderView);
+    IPython.notebook.widget_manager.register_widget_view('FloatSliderView', FloatSliderView);
 
 
-var FloatTextView = IPython.WidgetView.extend({
-    
-    // Called when view is rendered.
-    render : function(){
-        this.$el
-            .html('')
-            .addClass(this.model.comm.comm_id);
-        this.$textbox = $('<input type="text" />')
-            .addClass('input')
-            .appendTo(this.$el);
-        this.update(); // Set defaults.
-    },
-    
-    // Handles: Backend -> Frontend Sync
-    //          Frontent -> Frontend Sync
-    update : function(){
-        var value = this.model.get('value');
-        if (!this.changing && parseFloat(this.$textbox.val()) != value) {
-            this.$textbox.val(value);
-        }
+    var FloatTextView = IPython.WidgetView.extend({
         
-        if (this.model.get('disabled')) {
-            this.$textbox.attr('disabled','disabled');
-        } else {
-            this.$textbox.removeAttr('disabled');
-        }
-    },
-    
-    
-    events: {"keyup input" : "handleChanging",
-            "paste input" : "handleChanging",
-            "cut input" : "handleChanging",
-            "change input" : "handleChanged"}, // Fires only when control is validated or looses focus.
-    
-    // Handles and validates user input.
-    handleChanging: function(e) { 
+        // Called when view is rendered.
+        render : function(){
+            this.$el
+                .html('')
+                .addClass(this.model.comm.comm_id);
+            this.$textbox = $('<input type="text" />')
+                .addClass('input')
+                .appendTo(this.$el);
+            this.update(); // Set defaults.
+        },
         
-        // Try to parse value as a float.
-        var numericalValue = 0.0;
-        if (e.target.value != '') {
-            numericalValue = parseFloat(e.target.value);
-        }
+        // Handles: Backend -> Frontend Sync
+        //          Frontent -> Frontend Sync
+        update : function(){
+            var value = this.model.get('value');
+            if (!this.changing && parseFloat(this.$textbox.val()) != value) {
+                this.$textbox.val(value);
+            }
+            
+            if (this.model.get('disabled')) {
+                this.$textbox.attr('disabled','disabled');
+            } else {
+                this.$textbox.removeAttr('disabled');
+            }
+        },
         
-        // If parse failed, reset value to value stored in model.
-        if (isNaN(numericalValue)) {
-            e.target.value = this.model.get('value');
-        } else if (!isNaN(numericalValue)) {
-            numericalValue = Math.min(this.model.get('max'), numericalValue);
-            numericalValue = Math.max(this.model.get('min'), numericalValue);
+        
+        events: {"keyup input" : "handleChanging",
+                "paste input" : "handleChanging",
+                "cut input" : "handleChanging",
+                "change input" : "handleChanged"}, // Fires only when control is validated or looses focus.
+        
+        // Handles and validates user input.
+        handleChanging: function(e) { 
             
-            // Apply the value if it has changed.
-            if (numericalValue != this.model.get('value')) {
-                this.changing = true;
-                this.model.set('value', numericalValue);
-                this.model.apply(this);
-                this.changing = false;
+            // Try to parse value as a float.
+            var numericalValue = 0.0;
+            if (e.target.value != '') {
+                numericalValue = parseFloat(e.target.value);
+            }
+            
+            // If parse failed, reset value to value stored in model.
+            if (isNaN(numericalValue)) {
+                e.target.value = this.model.get('value');
+            } else if (!isNaN(numericalValue)) {
+                if (this.model.get('max') != undefined) {
+                    numericalValue = Math.min(this.model.get('max'), numericalValue);
+                }
+                if (this.model.get('min') != undefined) {
+                    numericalValue = Math.max(this.model.get('min'), numericalValue);
+                }
+
+                // Apply the value if it has changed.
+                if (numericalValue != this.model.get('value')) {
+                    this.changing = true;
+                    this.model.set('value', numericalValue);
+                    this.model.apply(this);
+                    this.changing = false;
+                }
+            }
+        },
+        
+        // Applies validated input.
+        handleChanged: function(e) { 
+            // Update the textbox
+            if (this.model.get('value') != e.target.value) {
+                e.target.value = this.model.get('value');
             }
         }
-    },
-    
-    // Applies validated input.
-    handleChanged: function(e) { 
-        // Update the textbox
-        if (this.model.get('value') != e.target.value) {
-            e.target.value = this.model.get('value');
-        }
-    }
-});
+    });
 
-IPython.notebook.widget_manager.register_widget_view('FloatTextView', FloatTextView);
+    IPython.notebook.widget_manager.register_widget_view('FloatTextView', FloatTextView);
+});
diff --git a/IPython/html/static/notebook/js/widgets/int_range.js b/IPython/html/static/notebook/js/widgets/int_range.js
index 996aeec..7ab5295 100644
--- a/IPython/html/static/notebook/js/widgets/int_range.js
+++ b/IPython/html/static/notebook/js/widgets/int_range.js
@@ -1,117 +1,123 @@
-var IntRangeWidgetModel = IPython.WidgetModel.extend({});
-IPython.notebook.widget_manager.register_widget_model('IntRangeWidgetModel', IntRangeWidgetModel);
+require(["notebook/js/widget"], function(){
+    var IntRangeWidgetModel = IPython.WidgetModel.extend({});
+    IPython.notebook.widget_manager.register_widget_model('IntRangeWidgetModel', IntRangeWidgetModel);
 
-var IntSliderView = IPython.WidgetView.extend({
-    
-    // Called when view is rendered.
-    render : function(){
-        this.$el.html('');
-        this.$slider = $('<div />')
-                        .slider({})
-                        .addClass('slider');
+    var IntSliderView = IPython.WidgetView.extend({
         
-        // Put the slider in a container 
-        this.$slider_container = $('<div />')
-                                .css('padding-top', '4px')
-                                .css('padding-bottom', '4px')
-                                .addClass(this.model.comm.comm_id)
-                                .append(this.$slider);    
-        this.$el.append(this.$slider_container);
+        // Called when view is rendered.
+        render : function(){
+            this.$el.html('');
+            this.$slider = $('<div />')
+                            .slider({})
+                            .addClass('slider');
+            
+            // Put the slider in a container 
+            this.$slider_container = $('<div />')
+                                    .css('padding-top', '4px')
+                                    .css('padding-bottom', '4px')
+                                    .addClass(this.model.comm.comm_id)
+                                    .append(this.$slider);    
+            this.$el.append(this.$slider_container);
+            
+            // Set defaults.
+            this.update();
+        },
         
-        // Set defaults.
-        this.update();
-    },
-    
-    // Handles: Backend -> Frontend Sync
-    //          Frontent -> Frontend Sync
-    update : function(){
-        // Slider related keys.
-        var _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation'];
-        for (var index in _keys) {
-            var key = _keys[index];
-            if (this.model.get(key) != undefined) {
-                this.$slider.slider("option", key, this.model.get(key));
+        // Handles: Backend -> Frontend Sync
+        //          Frontent -> Frontend Sync
+        update : function(){
+            // Slider related keys.
+            var _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation'];
+            for (var index in _keys) {
+                var key = _keys[index];
+                if (this.model.get(key) != undefined) {
+                    this.$slider.slider("option", key, this.model.get(key));
+                }
             }
-        }
-    },
-    
-    // Handles: User input
-    events: { "slide" : "handleSliderChange" }, 
-    handleSliderChange: function(e, ui) { 
-        this.model.set('value', ~~ui.value); // Double bit-wise not to truncate decimel
-        this.model.apply(this);
-    },
-});
+        },
+        
+        // Handles: User input
+        events: { "slide" : "handleSliderChange" }, 
+        handleSliderChange: function(e, ui) { 
+            this.model.set('value', ~~ui.value); // Double bit-wise not to truncate decimel
+            this.model.apply(this);
+        },
+    });
 
-IPython.notebook.widget_manager.register_widget_view('IntSliderView', IntSliderView);
+    IPython.notebook.widget_manager.register_widget_view('IntSliderView', IntSliderView);
 
-var IntTextView = IPython.WidgetView.extend({
-    
-    // Called when view is rendered.
-    render : function(){
-        this.$el
-            .html('')
-            .addClass(this.model.comm.comm_id);
-        this.$textbox = $('<input type="text" />')
-            .addClass('input')
-            .appendTo(this.$el);
-        this.update(); // Set defaults.
-    },
-    
-    // Handles: Backend -> Frontend Sync
-    //          Frontent -> Frontend Sync
-    update : function(){
-        var value = this.model.get('value');
-        if (!this.changing && parseInt(this.$textbox.val()) != value) {
-            this.$textbox.val(value);
-        }
+    var IntTextView = IPython.WidgetView.extend({
         
-        if (this.model.get('disabled')) {
-            this.$textbox.attr('disabled','disabled');
-        } else {
-            this.$textbox.removeAttr('disabled');
-        }
-    },
-    
-    
-    events: {"keyup input" : "handleChanging",
-            "paste input" : "handleChanging",
-            "cut input" : "handleChanging",
-            "change input" : "handleChanged"}, // Fires only when control is validated or looses focus.
-    
-    // Handles and validates user input.
-    handleChanging: function(e) { 
+        // Called when view is rendered.
+        render : function(){
+            this.$el
+                .html('')
+                .addClass(this.model.comm.comm_id);
+            this.$textbox = $('<input type="text" />')
+                .addClass('input')
+                .appendTo(this.$el);
+            this.update(); // Set defaults.
+        },
         
-        // Try to parse value as a float.
-        var numericalValue = 0;
-        if (e.target.value != '') {
-            numericalValue = parseInt(e.target.value);
-        }
+        // Handles: Backend -> Frontend Sync
+        //          Frontent -> Frontend Sync
+        update : function(){
+            var value = this.model.get('value');
+            if (!this.changing && parseInt(this.$textbox.val()) != value) {
+                this.$textbox.val(value);
+            }
+            
+            if (this.model.get('disabled')) {
+                this.$textbox.attr('disabled','disabled');
+            } else {
+                this.$textbox.removeAttr('disabled');
+            }
+        },
+        
+        
+        events: {"keyup input" : "handleChanging",
+                "paste input" : "handleChanging",
+                "cut input" : "handleChanging",
+                "change input" : "handleChanged"}, // Fires only when control is validated or looses focus.
         
-        // If parse failed, reset value to value stored in model.
-        if (isNaN(numericalValue)) {
-            e.target.value = this.model.get('value');
-        } else if (!isNaN(numericalValue)) {
-            numericalValue = Math.min(this.model.get('max'), numericalValue);
-            numericalValue = Math.max(this.model.get('min'), numericalValue);
+        // Handles and validates user input.
+        handleChanging: function(e) { 
             
-            // Apply the value if it has changed.
-            if (numericalValue != this.model.get('value')) {
-                this.changing = true;
-                this.model.set('value', numericalValue);
-                this.model.apply(this);
-                this.changing = false;
+            // Try to parse value as a float.
+            var numericalValue = 0;
+            if (e.target.value != '') {
+                numericalValue = parseInt(e.target.value);
+            }
+            
+            // If parse failed, reset value to value stored in model.
+            if (isNaN(numericalValue)) {
+                e.target.value = this.model.get('value');
+            } else if (!isNaN(numericalValue)) {
+                if (this.model.get('max') != undefined) {
+                    numericalValue = Math.min(this.model.get('max'), numericalValue);
+                }
+                if (this.model.get('min') != undefined) {
+                    numericalValue = Math.max(this.model.get('min'), numericalValue);
+                }
+                
+                // Apply the value if it has changed.
+                if (numericalValue != this.model.get('value')) {
+                    this.changing = true;
+                    this.model.set('value', numericalValue);
+                    this.model.apply(this);
+                    this.changing = false;
+                }
+            }
+        },
+        
+        // Applies validated input.
+        handleChanged: function(e) { 
+            // Update the textbox
+            if (this.model.get('value') != e.target.value) {
+                e.target.value = this.model.get('value');
             }
         }
-    },
-    
-    // Applies validated input.
-    handleChanged: function(e) { 
-        // Update the textbox
-        if (this.model.get('value') != e.target.value) {
-            e.target.value = this.model.get('value');
-        }
-    }
-});
+    });
 
-IPython.notebook.widget_manager.register_widget_view('IntTextView', IntTextView);
+    IPython.notebook.widget_manager.register_widget_view('IntTextView', IntTextView);
+});
diff --git a/IPython/html/static/notebook/js/widgets/selection.js b/IPython/html/static/notebook/js/widgets/selection.js
index 44dfe03..3ce9bef 100644
--- a/IPython/html/static/notebook/js/widgets/selection.js
+++ b/IPython/html/static/notebook/js/widgets/selection.js
@@ -1,194 +1,196 @@
-var SelectionWidgetModel = IPython.WidgetModel.extend({});
-IPython.notebook.widget_manager.register_widget_model('SelectionWidgetModel', SelectionWidgetModel);
+require(["notebook/js/widget"], function(){
+    var SelectionWidgetModel = IPython.WidgetModel.extend({});
+    IPython.notebook.widget_manager.register_widget_model('SelectionWidgetModel', SelectionWidgetModel);
 
-var DropdownView = IPython.WidgetView.extend({
-    
-    // Called when view is rendered.
-    render : function(){
+    var DropdownView = IPython.WidgetView.extend({
         
-        this.$el
-            .html('')
-            .addClass(this.model.comm.comm_id);
-        this.$buttongroup = $('<div />')
-                            .addClass('btn-group')
-                            .appendTo(this.$el);
-        this.$droplabel = $('<button />')
-                            .addClass('btn')
-                            .appendTo(this.$buttongroup);
-        this.$dropbutton = $('<button />')
-                            .addClass('btn')
-                            .addClass('dropdown-toggle')
-                            .attr('data-toggle', 'dropdown')
-                            .html('<span class="caret"></span>')
-                            .appendTo(this.$buttongroup);
-        this.$droplist = $('<ul />')
-                            .addClass('dropdown-menu')
-                            .appendTo(this.$buttongroup);
-        
-        // Set defaults.
-        this.update();
-    },
-    
-    // Handles: Backend -> Frontend Sync
-    //          Frontent -> Frontend Sync
-    update : function(){
-        this.$droplabel.html(this.model.get('value'));
-        
-        var items = this.model.get('values');
-        this.$droplist.html('');
-        for (var index in items) {
-            var that = this;
-            var item_button = $('<a href="#"/>')
-                .html(items[index])
-                .on('click', function(e){
-                    that.model.set('value', $(e.target).html(), this );
-                })
+        // Called when view is rendered.
+        render : function(){
             
-            this.$droplist.append($('<li />').append(item_button))
-        }
-        
-        if (this.model.get('disabled')) {
-            this.$buttongroup.attr('disabled','disabled');
-            this.$droplabel.attr('disabled','disabled');
-            this.$dropbutton.attr('disabled','disabled');
-            this.$droplist.attr('disabled','disabled');
-        } else {
-            this.$buttongroup.removeAttr('disabled');
-            this.$droplabel.removeAttr('disabled');
-            this.$dropbutton.removeAttr('disabled');
-            this.$droplist.removeAttr('disabled');
-        }
-    },
-    
-});
-
-IPython.notebook.widget_manager.register_widget_view('DropdownView', DropdownView);
-
-var RadioButtonView = IPython.WidgetView.extend({
-    
-    // Called when view is rendered.
-    render : function(){
-        this.$el
-            .html('')
-            .addClass(this.model.comm.comm_id);
-        this.update();
-    },
-    
-    // Handles: Backend -> Frontend Sync
-    //          Frontent -> Frontend Sync
-    update : function(){
+            this.$el
+                .html('')
+                .addClass(this.model.comm.comm_id);
+            this.$buttongroup = $('<div />')
+                                .addClass('btn-group')
+                                .appendTo(this.$el);
+            this.$droplabel = $('<button />')
+                                .addClass('btn')
+                                .appendTo(this.$buttongroup);
+            this.$dropbutton = $('<button />')
+                                .addClass('btn')
+                                .addClass('dropdown-toggle')
+                                .attr('data-toggle', 'dropdown')
+                                .html('<span class="caret"></span>')
+                                .appendTo(this.$buttongroup);
+            this.$droplist = $('<ul />')
+                                .addClass('dropdown-menu')
+                                .appendTo(this.$buttongroup);
+            
+            // Set defaults.
+            this.update();
+        },
         
-        // Add missing items to the DOM.
-        var items = this.model.get('values');
-        for (var index in items) {
-            var item_query = ' :input[value="' + items[index] + '"]';
-            if (this.$el.find(item_query).length == 0) {
-                var $label = $('<label />')
-                    .addClass('radio')
-                    .html(items[index])
-                    .appendTo(this.$el);
-                
+        // Handles: Backend -> Frontend Sync
+        //          Frontent -> Frontend Sync
+        update : function(){
+            this.$droplabel.html(this.model.get('value'));
+            
+            var items = this.model.get('values');
+            this.$droplist.html('');
+            for (var index in items) {
                 var that = this;
-                $('<input />')
-                    .attr('type', 'radio')
-                    .addClass(this.model)
-                    .val(items[index])
-                    .prependTo($label)
+                var item_button = $('<a href="#"/>')
+                    .html(items[index])
                     .on('click', function(e){
-                        that.model.set('value', $(e.target).val(), this);
-                        that.model.apply();
-                    });
+                        that.model.set('value', $(e.target).html(), this );
+                    })
+                
+                this.$droplist.append($('<li />').append(item_button))
             }
             
-            if (this.model.get('value') == items[index]) {
-                this.$el.find(item_query).prop('checked', true);
+            if (this.model.get('disabled')) {
+                this.$buttongroup.attr('disabled','disabled');
+                this.$droplabel.attr('disabled','disabled');
+                this.$dropbutton.attr('disabled','disabled');
+                this.$droplist.attr('disabled','disabled');
             } else {
-                this.$el.find(item_query).prop('checked', false);
+                this.$buttongroup.removeAttr('disabled');
+                this.$droplabel.removeAttr('disabled');
+                this.$dropbutton.removeAttr('disabled');
+                this.$droplist.removeAttr('disabled');
             }
-        }
+        },
+        
+    });
+
+    IPython.notebook.widget_manager.register_widget_view('DropdownView', DropdownView);
+
+    var RadioButtonsView = IPython.WidgetView.extend({
+        
+        // Called when view is rendered.
+        render : function(){
+            this.$el
+                .html('')
+                .addClass(this.model.comm.comm_id);
+            this.update();
+        },
         
-        // Remove items that no longer exist.
-        this.$el.find('input').each(function(i, obj) {
-            var value = $(obj).val();
-            var found = false;
+        // Handles: Backend -> Frontend Sync
+        //          Frontent -> Frontend Sync
+        update : function(){
+            
+            // Add missing items to the DOM.
+            var items = this.model.get('values');
             for (var index in items) {
-                if (items[index] == value) {
-                    found = true;
-                    break;
+                var item_query = ' :input[value="' + items[index] + '"]';
+                if (this.$el.find(item_query).length == 0) {
+                    var $label = $('<label />')
+                        .addClass('radio')
+                        .html(items[index])
+                        .appendTo(this.$el);
+                    
+                    var that = this;
+                    $('<input />')
+                        .attr('type', 'radio')
+                        .addClass(this.model)
+                        .val(items[index])
+                        .prependTo($label)
+                        .on('click', function(e){
+                            that.model.set('value', $(e.target).val(), this);
+                            that.model.apply();
+                        });
+                }
+                
+                if (this.model.get('value') == items[index]) {
+                    this.$el.find(item_query).prop('checked', true);
+                } else {
+                    this.$el.find(item_query).prop('checked', false);
                 }
             }
             
-            if (!found) {
-                $(obj).parent().remove();
-            }
-        });
-    },
-    
-});
+            // Remove items that no longer exist.
+            this.$el.find('input').each(function(i, obj) {
+                var value = $(obj).val();
+                var found = false;
+                for (var index in items) {
+                    if (items[index] == value) {
+                        found = true;
+                        break;
+                    }
+                }
+                
+                if (!found) {
+                    $(obj).parent().remove();
+                }
+            });
+        },
+        
+    });
 
-IPython.notebook.widget_manager.register_widget_view('RadioButtonView', RadioButtonView);
+    IPython.notebook.widget_manager.register_widget_view('RadioButtonsView', RadioButtonsView);
 
 
-var ToggleButtonView = IPython.WidgetView.extend({
-    
-    // Called when view is rendered.
-    render : function(){
-        this.$el
-            .html('')
-            .addClass(this.model.comm.comm_id);
-        this.$buttongroup = $('<div />')
-            .addClass('btn-group')
-            .attr('data-toggle', 'buttons-radio')
-            .appendTo(this.$el);
-        this.update();
-    },
-    
-    // Handles: Backend -> Frontend Sync
-    //          Frontent -> Frontend Sync
-    update : function(){
+    var ToggleButtonsView = IPython.WidgetView.extend({
         
-        // Add missing items to the DOM.
-        var items = this.model.get('values');
-        for (var index in items) {
-            var item_query = ' :contains("' + items[index] + '")';
-            if (this.$buttongroup.find(item_query).length == 0) {
-                
-                var that = this;
-                $('<button />')
-                    .attr('type', 'button')
-                    .addClass('btn')
-                    .html(items[index])
-                    .appendTo(this.$buttongroup)
-                    .on('click', function(e){
-                        that.model.set('value', $(e.target).html(), this);
-                        that.model.apply();
-                    });
-            }
-            
-            if (this.model.get('value') == items[index]) {
-                this.$buttongroup.find(item_query).addClass('active');
-            } else {
-                this.$buttongroup.find(item_query).removeClass('active');
-            }
-        }
+        // Called when view is rendered.
+        render : function(){
+            this.$el
+                .html('')
+                .addClass(this.model.comm.comm_id);
+            this.$buttongroup = $('<div />')
+                .addClass('btn-group')
+                .attr('data-toggle', 'buttons-radio')
+                .appendTo(this.$el);
+            this.update();
+        },
         
-        // Remove items that no longer exist.
-        this.$buttongroup.find('button').each(function(i, obj) {
-            var value = $(obj).html();
-            var found = false;
+        // Handles: Backend -> Frontend Sync
+        //          Frontent -> Frontend Sync
+        update : function(){
+            
+            // Add missing items to the DOM.
+            var items = this.model.get('values');
             for (var index in items) {
-                if (items[index] == value) {
-                    found = true;
-                    break;
+                var item_query = ' :contains("' + items[index] + '")';
+                if (this.$buttongroup.find(item_query).length == 0) {
+                    
+                    var that = this;
+                    $('<button />')
+                        .attr('type', 'button')
+                        .addClass('btn')
+                        .html(items[index])
+                        .appendTo(this.$buttongroup)
+                        .on('click', function(e){
+                            that.model.set('value', $(e.target).html(), this);
+                            that.model.apply();
+                        });
+                }
+                
+                if (this.model.get('value') == items[index]) {
+                    this.$buttongroup.find(item_query).addClass('active');
+                } else {
+                    this.$buttongroup.find(item_query).removeClass('active');
                 }
             }
             
-            if (!found) {
-                $(obj).remove();
-            }
-        });
-    },
-    
-});
+            // Remove items that no longer exist.
+            this.$buttongroup.find('button').each(function(i, obj) {
+                var value = $(obj).html();
+                var found = false;
+                for (var index in items) {
+                    if (items[index] == value) {
+                        found = true;
+                        break;
+                    }
+                }
+                
+                if (!found) {
+                    $(obj).remove();
+                }
+            });
+        },
+        
+    });
 
-IPython.notebook.widget_manager.register_widget_view('ToggleButtonView', ToggleButtonView);
+    IPython.notebook.widget_manager.register_widget_view('ToggleButtonsView', ToggleButtonsView);
+});
diff --git a/IPython/html/static/notebook/js/widgets/string.js b/IPython/html/static/notebook/js/widgets/string.js
index cc7c930..4684fc7 100644
--- a/IPython/html/static/notebook/js/widgets/string.js
+++ b/IPython/html/static/notebook/js/widgets/string.js
@@ -1,74 +1,98 @@
-var StringWidgetModel = IPython.WidgetModel.extend({});
-IPython.notebook.widget_manager.register_widget_model('StringWidgetModel', StringWidgetModel);
+require(["notebook/js/widget"], function(){
+    var StringWidgetModel = IPython.WidgetModel.extend({});
+    IPython.notebook.widget_manager.register_widget_model('StringWidgetModel', StringWidgetModel);
 
-var TextareaView = IPython.WidgetView.extend({
-  
-    // Called when view is rendered.
-    render : function(){
-        this.$el
-            .html('')
-            .addClass(this.model.comm.comm_id);
-        this.$textbox = $('<textarea />')
-            .attr('rows', 5)
-            .appendTo(this.$el);
-        this.update(); // Set defaults.
-    },
-    
-    // Handles: Backend -> Frontend Sync
-    //          Frontent -> Frontend Sync
-    update : function(){
-        if (!this.user_invoked_update) {
-            this.$textbox.val(this.model.get('value'));
-        }
-    },
-    
-    events: {"keyup textarea" : "handleChanging",
-            "paste textarea" : "handleChanging",
-            "cut textarea" : "handleChanging"},
-    
-    // Handles and validates user input.
-    handleChanging: function(e) { 
-        this.user_invoked_update = true;
-        this.model.set('value', e.target.value);
-        this.model.apply(this);
-        this.user_invoked_update = false;
-    },
-});
+    var LabelView = IPython.WidgetView.extend({
+      
+        // Called when view is rendered.
+        render : function(){
+            this.$el
+                .html('');
+            this.$label = $('<div />')
+                .addClass(this.model.comm.comm_id)
+                .appendTo(this.$el);
+            this.update(); // Set defaults.
+        },
+        
+        // Handles: Backend -> Frontend Sync
+        //          Frontent -> Frontend Sync
+        update : function(){
+            this.$label.html(this.model.get('value'));
+        },
+        
+    });
 
-IPython.notebook.widget_manager.register_widget_view('TextareaView', TextareaView);
+    IPython.notebook.widget_manager.register_widget_view('LabelView', LabelView);
 
-var TextboxView = IPython.WidgetView.extend({
-  
-    // Called when view is rendered.
-    render : function(){
-        this.$el
-            .html('')
-            .addClass(this.model.comm.comm_id);
-        this.$textbox = $('<input type="text" />')
-            .addClass('input')
-            .appendTo(this.$el);
-        this.update(); // Set defaults.
-    },
-    
-    // Handles: Backend -> Frontend Sync
-    //          Frontent -> Frontend Sync
-    update : function(){
-        if (!this.user_invoked_update) {
-            this.$textbox.val(this.model.get('value'));
-        }
-    },
-    
-    events: {"keyup input" : "handleChanging",
-            "paste input" : "handleChanging",
-            "cut input" : "handleChanging"},
-    
-    // Handles and validates user input.
-    handleChanging: function(e) { 
-        this.user_invoked_update = true;
-        this.model.set('value', e.target.value);
-        this.model.apply(this);
-        this.user_invoked_update = false;
-    },
-});
+    var TextareaView = IPython.WidgetView.extend({
+      
+        // Called when view is rendered.
+        render : function(){
+            this.$el
+                .html('')
+                .addClass(this.model.comm.comm_id);
+            this.$textbox = $('<textarea />')
+                .attr('rows', 5)
+                .appendTo(this.$el);
+            this.update(); // Set defaults.
+        },
+        
+        // Handles: Backend -> Frontend Sync
+        //          Frontent -> Frontend Sync
+        update : function(){
+            if (!this.user_invoked_update) {
+                this.$textbox.val(this.model.get('value'));
+            }
+        },
+        
+        events: {"keyup textarea" : "handleChanging",
+                "paste textarea" : "handleChanging",
+                "cut textarea" : "handleChanging"},
+        
+        // Handles and validates user input.
+        handleChanging: function(e) { 
+            this.user_invoked_update = true;
+            this.model.set('value', e.target.value);
+            this.model.apply(this);
+            this.user_invoked_update = false;
+        },
+    });
+
+    IPython.notebook.widget_manager.register_widget_view('TextareaView', TextareaView);
 
-IPython.notebook.widget_manager.register_widget_view('TextboxView', TextboxView);
+    var TextboxView = IPython.WidgetView.extend({
+      
+        // Called when view is rendered.
+        render : function(){
+            this.$el
+                .html('')
+                .addClass(this.model.comm.comm_id);
+            this.$textbox = $('<input type="text" />')
+                .addClass('input')
+                .appendTo(this.$el);
+            this.update(); // Set defaults.
+        },
+        
+        // Handles: Backend -> Frontend Sync
+        //          Frontent -> Frontend Sync
+        update : function(){
+            if (!this.user_invoked_update) {
+                this.$textbox.val(this.model.get('value'));
+            }
+        },
+        
+        events: {"keyup input" : "handleChanging",
+                "paste input" : "handleChanging",
+                "cut input" : "handleChanging"},
+        
+        // Handles and validates user input.
+        handleChanging: function(e) { 
+            this.user_invoked_update = true;
+            this.model.set('value', e.target.value);
+            this.model.apply(this);
+            this.user_invoked_update = false;
+        },
+    });
+
+    IPython.notebook.widget_manager.register_widget_view('TextboxView', TextboxView);
+});
diff --git a/IPython/html/templates/page.html b/IPython/html/templates/page.html
index 25539ca..5bef21d 100644
--- a/IPython/html/templates/page.html
+++ b/IPython/html/templates/page.html
@@ -71,8 +71,6 @@
 <script src="{{static_url("components/jquery/jquery.min.js") }}" type="text/javascript" charset="utf-8"></script>
 <script src="{{static_url("components/jquery-ui/ui/minified/jquery-ui.min.js") }}" type="text/javascript" charset="utf-8"></script>
 <script src="{{static_url("components/bootstrap/bootstrap/js/bootstrap.min.js") }}" type="text/javascript" charset="utf-8"></script>
-<script src="{{static_url("components/underscore/underscore-min.js") }}" type="text/javascript" charset="utf-8"></script>
-<script src="{{static_url("components/backbone/backbone-min.js") }}" type="text/javascript" charset="utf-8"></script>
 <script src="{{static_url("base/js/namespace.js") }}" type="text/javascript" charset="utf-8"></script>
 <script src="{{static_url("base/js/page.js") }}" type="text/javascript" charset="utf-8"></script>
 <script src="{{static_url("auth/js/loginwidget.js") }}" type="text/javascript" charset="utf-8"></script>