Index: src/wp-admin/css/customize-widgets.css
===================================================================
--- src/wp-admin/css/customize-widgets.css	(revision 27974)
+++ src/wp-admin/css/customize-widgets.css	(working copy)
@@ -108,13 +108,6 @@
 	display: none;
 }
 
-
-/* MP6-compat */
-#customize-theme-controls .accordion-section-content .widget {
-	color: black;
-}
-
-
 /**
 * Widget reordering styles
 **/
@@ -326,7 +319,7 @@
 
 body.adding-widget .add-new-widget,
 body.adding-widget .add-new-widget:hover {
-	background: #EEE;
+	background: #eee;
 	border-color: #999;
 	color: #333;
 	-webkit-box-shadow: inset 0 2px 5px -3px rgba(0, 0, 0, 0.5);
Index: src/wp-admin/js/customize-widgets.js
===================================================================
--- src/wp-admin/js/customize-widgets.js	(revision 27974)
+++ src/wp-admin/js/customize-widgets.js	(working copy)
@@ -1,45 +1,23 @@
-/*global wp, Backbone, _, jQuery, WidgetCustomizer_exports */
-/*exported WidgetCustomizer */
-var WidgetCustomizer = ( function ($) {
-	'use strict';
+/* global _wpCustomizeWidgetsSettings */
+(function( wp, $ ){
 
-	var Widget,
-		WidgetCollection,
-		Sidebar,
-		SidebarCollection,
-		OldPreviewer,
-		builtin_form_sync_handlers,
-		customize = wp.customize, self = {
-		nonce: null,
-		i18n: {
-			save_btn_label: '',
-			save_btn_tooltip: '',
-			remove_btn_label: '',
-			remove_btn_tooltip: '',
-			error: ''
-		},
-		available_widgets: [], // available widgets for instantiating
-		registered_widgets: [], // all widgets registered
-		active_sidebar_control: null,
-		previewer: null,
-		saved_widget_ids: {},
-		registered_sidebars: [],
-		tpl: {
-			move_widget_area: '',
-			widget_reorder_nav: ''
-		}
-	};
-	$.extend( self, WidgetCustomizer_exports );
+	if ( ! wp || ! wp.customize ) { return; }
 
-	// Lots of widgets expect this old ajaxurl global to be available
-	if ( typeof window.ajaxurl === 'undefined' ) {
-		window.ajaxurl = wp.ajax.settings.url;
-	}
+	// Set up our namespace...
+	var api = wp.customize,
+		l10n, OldPreviewer;
 
+	api.Widgets = api.Widgets || {};
+
+	// Link settings
+	api.Widgets.data = _wpCustomizeWidgetsSettings || {};
+	l10n = api.Widgets.data.l10n;
+	delete api.Widgets.data.l10n;
+
 	/**
 	 * Set up model
 	 */
-	Widget = self.Widget = Backbone.Model.extend( {
+	api.Widgets.WidgetModel = Backbone.Model.extend({
 		id: null,
 		temp_id: null,
 		classname: null,
@@ -56,8 +34,8 @@
 		height: null
 	} );
 
-	WidgetCollection = self.WidgetCollection = Backbone.Collection.extend( {
-		model: Widget,
+	api.Widgets.WidgetCollection = Backbone.Collection.extend({
+		model: api.Widgets.WidgetModel,
 
 		// Controls searching on the current widget collection
 		// and triggers an update event
@@ -80,7 +58,7 @@
 			// If search is blank, show all themes
 			// Useful for resetting the views when you clean the input
 			if ( this.terms === '' ) {
-				this.reset( WidgetCustomizer_exports.available_widgets );
+				this.reset( api.Widgets.data.availableWidgets );
 			}
 
 			// Trigger an 'update' event
@@ -93,7 +71,7 @@
 			var match, results, haystack;
 
 			// Start with a full collection
-			this.reset( WidgetCustomizer_exports.available_widgets, { silent: true } );
+			this.reset( api.Widgets.data.availableWidgets, { silent: true } );
 
 			// Escape the term string for RegExp meta characters
 			term = term.replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' );
@@ -112,9 +90,9 @@
 			this.reset( results );
 		}
 	} );
-	self.available_widgets = new WidgetCollection( self.available_widgets );
+	api.Widgets.availableWidgets = new api.Widgets.WidgetCollection( api.Widgets.data.availableWidgets );
 
-	Sidebar = self.Sidebar = Backbone.Model.extend( {
+	api.Widgets.SidebarModel = Backbone.Model.extend({
 		after_title: null,
 		after_widget: null,
 		before_title: null,
@@ -126,500 +104,42 @@
 		is_rendered: false
 	} );
 
-	SidebarCollection = self.SidebarCollection = Backbone.Collection.extend( {
-		model: Sidebar
+	api.Widgets.SidebarCollection = Backbone.Collection.extend({
+		model: api.Widgets.SidebarModel
 	} );
-	self.registered_sidebars = new SidebarCollection( self.registered_sidebars );
+	api.Widgets.registeredSidebars = new api.Widgets.SidebarCollection( api.Widgets.data.registeredSidebars );
 
 	/**
 	 * Handlers for the widget-synced event, organized by widget ID base.
 	 * Other widgets may provide their own update handlers by adding
 	 * listeners for the widget-synced event.
 	 */
-	builtin_form_sync_handlers = {
+	api.Widgets.formSyncHandlers = {
 
 		/**
 		 * @param {jQuery.Event} e
-		 * @param {jQuery} widget_el
-		 * @param {String} new_form
+		 * @param {jQuery} widget
+		 * @param {String} newForm
 		 */
-		rss: function ( e, widget_el, new_form ) {
-			var old_widget_error = widget_el.find( '.widget-error:first' ),
-				new_widget_error = $( '<div>' + new_form + '</div>' ).find( '.widget-error:first' );
+		rss: function ( e, widget, newForm ) {
+			var oldWidgetError = widget.find( '.widget-error:first' ),
+				newWidgetError = $( '<div>' + newForm + '</div>' ).find( '.widget-error:first' );
 
-			if ( old_widget_error.length && new_widget_error.length ) {
-				old_widget_error.replaceWith( new_widget_error );
-			} else if ( old_widget_error.length ) {
-				old_widget_error.remove();
-			} else if ( new_widget_error.length ) {
-				widget_el.find( '.widget-content:first' ).prepend( new_widget_error );
+			if ( oldWidgetError.length && newWidgetError.length ) {
+				oldWidgetError.replaceWith( newWidgetError );
+			} else if ( oldWidgetError.length ) {
+				oldWidgetError.remove();
+			} else if ( newWidgetError.length ) {
+				widget.find( '.widget-content:first' ).prepend( newWidgetError );
 			}
 		}
 	};
 
 	/**
-	 * On DOM ready, initialize some meta functionality independent of specific
-	 * customizer controls.
-	 */
-	self.init = function () {
-		this.availableWidgetsPanel.setup();
-
-		// Highlight widget control
-		this.previewer.bind( 'highlight-widget-control', self.highlightWidgetFormControl );
-
-		// Open and focus widget control
-		this.previewer.bind( 'focus-widget-control', self.focusWidgetFormControl );
-	};
-	wp.customize.bind( 'ready', function () {
-		self.init();
-	} );
-
-	/**
-	 * Sidebar Widgets control
-	 * Note that 'sidebar_widgets' must match the Sidebar_Widgets_WP_Customize_Control::$type
-	 */
-	customize.controlConstructor.sidebar_widgets = customize.Control.extend( {
-
-		/**
-		 * Set up the control
-		 */
-		ready: function() {
-			var control = this;
-			control.control_section = control.container.closest( '.control-section' );
-			control.section_content = control.container.closest( '.accordion-section-content' );
-			control._setupModel();
-			control._setupSortable();
-			control._setupAddition();
-			control._applyCardinalOrderClassNames();
-		},
-
-		/**
-		 * Update ordering of widget control forms when the setting is updated
-		 */
-		_setupModel: function() {
-			var control = this,
-				registered_sidebar = self.registered_sidebars.get( control.params.sidebar_id );
-
-			control.setting.bind( function( new_widget_ids, old_widget_ids ) {
-				var widget_form_controls,
-					sidebar_widgets_add_control,
-					final_control_containers,
-					removed_widget_ids = _( old_widget_ids ).difference( new_widget_ids );
-
-				// Filter out any persistent widget_ids for widgets which have been deactivated
-				new_widget_ids = _( new_widget_ids ).filter( function ( new_widget_id ) {
-					var parsed_widget_id = parse_widget_id( new_widget_id );
-					return !! self.available_widgets.findWhere( { id_base: parsed_widget_id.id_base } );
-				} );
-
-				widget_form_controls = _( new_widget_ids ).map( function ( widget_id ) {
-					var widget_form_control = self.getWidgetFormControlForWidget( widget_id );
-					if ( ! widget_form_control ) {
-						widget_form_control = control.addWidget( widget_id );
-					}
-					return widget_form_control;
-				} );
-
-				// Sort widget controls to their new positions
-				widget_form_controls.sort( function ( a, b ) {
-					var a_index = _.indexOf( new_widget_ids, a.params.widget_id ),
-						b_index = _.indexOf( new_widget_ids, b.params.widget_id );
-					if ( a_index === b_index ) {
-						return 0;
-					}
-					return a_index < b_index ? -1 : 1;
-				} );
-
-				sidebar_widgets_add_control = control.section_content.find( '.customize-control-sidebar_widgets' );
-
-				// Append the controls to put them in the right order
-				final_control_containers = _( widget_form_controls ).map( function( widget_form_controls ) {
-					return widget_form_controls.container[0];
-				} );
-
-				// Re-sort widget form controls (including widgets form other sidebars newly moved here)
-				sidebar_widgets_add_control.before( final_control_containers );
-				control._applyCardinalOrderClassNames();
-
-				// If the widget was dragged into the sidebar, make sure the sidebar_id param is updated
-				_( widget_form_controls ).each( function ( widget_form_control ) {
-					widget_form_control.params.sidebar_id = control.params.sidebar_id;
-				} );
-
-				// Cleanup after widget removal
-				_( removed_widget_ids ).each( function ( removed_widget_id ) {
-
-					// Using setTimeout so that when moving a widget to another sidebar, the other sidebars_widgets settings get a chance to update
-					setTimeout( function () {
-						var is_present_in_another_sidebar = false,
-							removed_control,
-							was_dragged_to_another_sidebar,
-							inactive_widgets,
-							removed_id_base,
-							widget;
-
-						// Check if the widget is in another sidebar
-						wp.customize.each( function ( other_setting ) {
-							if ( other_setting.id === control.setting.id || 0 !== other_setting.id.indexOf( 'sidebars_widgets[' ) || other_setting.id === 'sidebars_widgets[wp_inactive_widgets]' ) {
-								return;
-							}
-							var other_sidebar_widgets = other_setting(), i;
-
-							i = _.indexOf( other_sidebar_widgets, removed_widget_id );
-							if ( -1 !== i ) {
-								is_present_in_another_sidebar = true;
-							}
-						} );
-
-						// If the widget is present in another sidebar, abort!
-						if ( is_present_in_another_sidebar ) {
-							return;
-						}
-
-						removed_control = self.getWidgetFormControlForWidget( removed_widget_id );
-
-						// Detect if widget control was dragged to another sidebar
-						was_dragged_to_another_sidebar = (
-							removed_control &&
-							$.contains( document, removed_control.container[0] ) &&
-							! $.contains( control.section_content[0], removed_control.container[0] )
-						);
-
-						// Delete any widget form controls for removed widgets
-						if ( removed_control && ! was_dragged_to_another_sidebar ) {
-							wp.customize.control.remove( removed_control.id );
-							removed_control.container.remove();
-						}
-
-						// Move widget to inactive widgets sidebar (move it to trash) if has been previously saved
-						// This prevents the inactive widgets sidebar from overflowing with throwaway widgets
-						if ( self.saved_widget_ids[removed_widget_id] ) {
-							inactive_widgets = wp.customize.value( 'sidebars_widgets[wp_inactive_widgets]' )().slice();
-							inactive_widgets.push( removed_widget_id );
-							wp.customize.value( 'sidebars_widgets[wp_inactive_widgets]' )( _( inactive_widgets ).unique() );
-						}
-
-						// Make old single widget available for adding again
-						removed_id_base = parse_widget_id( removed_widget_id ).id_base;
-						widget = self.available_widgets.findWhere( { id_base: removed_id_base } );
-						if ( widget && ! widget.get( 'is_multi' ) ) {
-							widget.set( 'is_disabled', false );
-						}
-					} );
-
-				} );
-			} );
-
-			// Update the model with whether or not the sidebar is rendered
-			self.previewer.bind( 'rendered-sidebars', function ( rendered_sidebars ) {
-				var is_rendered = !! rendered_sidebars[control.params.sidebar_id];
-				registered_sidebar.set( 'is_rendered', is_rendered );
-			} );
-
-			// Show the sidebar section when it becomes visible
-			registered_sidebar.on( 'change:is_rendered', function ( ) {
-				var section_selector = '#accordion-section-sidebar-widgets-' + this.get( 'id' ), section;
-				section = $( section_selector );
-				if ( this.get( 'is_rendered' ) ) {
-					section.stop().slideDown( function () {
-						$( this ).css( 'height', 'auto' ); // so that the .accordion-section-content won't overflow
-					} );
-				} else {
-					// Make sure that hidden sections get closed first
-					if ( section.hasClass( 'open' ) ) {
-						// it would be nice if accordionSwitch() in accordion.js was public
-						section.find( '.accordion-section-title' ).trigger( 'click' );
-					}
-					section.stop().slideUp();
-				}
-			} );
-		},
-
-		/**
-		 * Allow widgets in sidebar to be re-ordered, and for the order to be previewed
-		 */
-		_setupSortable: function () {
-			var control = this;
-			control.is_reordering = false;
-
-			/**
-			 * Update widget order setting when controls are re-ordered
-			 */
-			control.section_content.sortable( {
-				items: '> .customize-control-widget_form',
-				handle: '.widget-top',
-				axis: 'y',
-				connectWith: '.accordion-section-content:has(.customize-control-sidebar_widgets)',
-				update: function () {
-					var widget_container_ids = control.section_content.sortable( 'toArray' ), widget_ids;
-					widget_ids = $.map( widget_container_ids, function ( widget_container_id ) {
-						return $( '#' + widget_container_id ).find( ':input[name=widget-id]' ).val();
-					} );
-					control.setting( widget_ids );
-				}
-			} );
-
-			/**
-			 * Expand other customizer sidebar section when dragging a control widget over it,
-			 * allowing the control to be dropped into another section
-			 */
-			control.control_section.find( '.accordion-section-title' ).droppable( {
-				accept: '.customize-control-widget_form',
-				over: function () {
-					if ( ! control.control_section.hasClass( 'open' ) ) {
-						control.control_section.addClass( 'open' );
-						control.section_content.toggle( false ).slideToggle( 150, function () {
-							control.section_content.sortable( 'refreshPositions' );
-						} );
-					}
-				}
-			} );
-
-			/**
-			 * Keyboard-accessible reordering
-			 */
-			control.container.find( '.reorder-toggle' ).on( 'click keydown', function( event ) {
-				if ( event.type === 'keydown' && ! ( event.which === 13 || event.which === 32 ) ) { // Enter or Spacebar
-					return;
-				}
-
-				control.toggleReordering( ! control.is_reordering );
-			} );
-		},
-
-		/**
-		 * Set up UI for adding a new widget
-		 */
-		_setupAddition: function () {
-			var control = this;
-
-			control.container.find( '.add-new-widget' ).on( 'click keydown', function( event ) {
-				if ( event.type === 'keydown' && ! ( event.which === 13 || event.which === 32 ) ) { // Enter or Spacebar
-					return;
-				}
-
-				if ( control.section_content.hasClass( 'reordering' ) ) {
-					return;
-				}
-
-				// @todo Use an control.is_adding state
-				if ( ! $( 'body' ).hasClass( 'adding-widget' ) ) {
-					self.availableWidgetsPanel.open( control );
-				} else {
-					self.availableWidgetsPanel.close();
-				}
-			} );
-		},
-
-		/**
-		 * Add classes to the widget_form controls to assist with styling
-		 */
-		_applyCardinalOrderClassNames: function () {
-			var control = this;
-			control.section_content.find( '.customize-control-widget_form' )
-				.removeClass( 'first-widget' )
-				.removeClass( 'last-widget' )
-				.find( '.move-widget-down, .move-widget-up' ).prop( 'tabIndex', 0 );
-
-			control.section_content.find( '.customize-control-widget_form:first' )
-				.addClass( 'first-widget' )
-				.find( '.move-widget-up' ).prop( 'tabIndex', -1 );
-			control.section_content.find( '.customize-control-widget_form:last' )
-				.addClass( 'last-widget' )
-				.find( '.move-widget-down' ).prop( 'tabIndex', -1 );
-		},
-
-
-		/***********************************************************************
-		 * Begin public API methods
-		 **********************************************************************/
-
-		/**
-		 * Enable/disable the reordering UI
-		 *
-		 * @param {Boolean} toggle to enable/disable reordering
-		 */
-		toggleReordering: function ( toggle ) {
-			var control = this;
-			toggle = Boolean( toggle );
-			if ( toggle === control.section_content.hasClass( 'reordering' ) ) {
-				return;
-			}
-
-			control.is_reordering = toggle;
-			control.section_content.toggleClass( 'reordering', toggle );
-
-			if ( toggle ) {
-				_( control.getWidgetFormControls() ).each( function ( form_control ) {
-					form_control.collapseForm();
-				} );
-			}
-		},
-
-		/**
-		 * @return {wp.customize.controlConstructor.widget_form[]}
-		 */
-		getWidgetFormControls: function () {
-			var control = this, form_controls;
-
-			form_controls = _( control.setting() ).map( function ( widget_id ) {
-				var setting_id = widget_id_to_setting_id( widget_id ),
-					form_control = customize.control( setting_id );
-
-				if ( ! form_control ) {
-					throw new Error( 'Unable to find widget_form control for ' + widget_id );
-				}
-				return form_control;
-			} );
-			return form_controls;
-		},
-
-		/**
-		 * @param {string} widget_id or an id_base for adding a previously non-existing widget
-		 * @returns {object} widget_form control instance
-		 */
-		addWidget: function ( widget_id ) {
-			var control = this,
-				control_html,
-				widget_el,
-				customize_control_type = 'widget_form',
-				customize_control,
-				parsed_widget_id = parse_widget_id( widget_id ),
-				widget_number = parsed_widget_id.number,
-				widget_id_base = parsed_widget_id.id_base,
-				widget = self.available_widgets.findWhere( {id_base: widget_id_base} ),
-				setting_id,
-				is_existing_widget,
-				Constructor,
-				widget_form_control,
-				sidebar_widgets,
-				setting_args;
-
-			if ( ! widget ) {
-				throw new Error( 'Widget unexpectedly not found.' );
-			}
-			if ( widget_number && ! widget.get( 'is_multi' ) ) {
-				throw new Error( 'Did not expect a widget number to be supplied for a non-multi widget' );
-			}
-
-			// Set up new multi widget
-			if ( widget.get( 'is_multi' ) && ! widget_number ) {
-				widget.set( 'multi_number', widget.get( 'multi_number' ) + 1 );
-				widget_number = widget.get( 'multi_number' );
-			}
-
-			control_html = $( '#widget-tpl-' + widget.get( 'id' ) ).html();
-			if ( widget.get( 'is_multi' ) ) {
-				control_html = control_html.replace( /<[^<>]+>/g, function ( m ) {
-					return m.replace( /__i__|%i%/g, widget_number );
-				} );
-			} else {
-				widget.set( 'is_disabled', true ); // Prevent single widget from being added again now
-			}
-			widget_el = $( control_html );
-
-			customize_control = $( '<li></li>' );
-			customize_control.addClass( 'customize-control' );
-			customize_control.addClass( 'customize-control-' + customize_control_type );
-			customize_control.append( widget_el );
-			customize_control.find( '> .widget-icon' ).remove();
-			if ( widget.get( 'is_multi' ) ) {
-				customize_control.find( 'input[name="widget_number"]' ).val( widget_number );
-				customize_control.find( 'input[name="multi_number"]' ).val( widget_number );
-			}
-			widget_id = customize_control.find( '[name="widget-id"]' ).val();
-			customize_control.hide(); // to be slid-down below
-
-			setting_id = 'widget_' + widget.get( 'id_base' );
-			if ( widget.get( 'is_multi' ) ) {
-				setting_id += '[' + widget_number + ']';
-			}
-			customize_control.attr( 'id', 'customize-control-' + setting_id.replace( /\]/g, '' ).replace( /\[/g, '-' ) );
-
-			control.container.after( customize_control );
-
-			// Only create setting if it doesn't already exist (if we're adding a pre-existing inactive widget)
-			is_existing_widget = wp.customize.has( setting_id );
-			if ( ! is_existing_widget ) {
-				setting_args = {
-					transport: 'refresh',
-					previewer: control.setting.previewer
-				};
-				wp.customize.create( setting_id, setting_id, {}, setting_args );
-			}
-
-			Constructor = wp.customize.controlConstructor[customize_control_type];
-			widget_form_control = new Constructor( setting_id, {
-				params: {
-					settings: {
-						'default': setting_id
-					},
-					sidebar_id: control.params.sidebar_id,
-					widget_id: widget_id,
-					widget_id_base: widget.get( 'id_base' ),
-					type: customize_control_type,
-					is_new: ! is_existing_widget,
-					width: widget.get( 'width' ),
-					height: widget.get( 'height' ),
-					is_wide: widget.get( 'is_wide' )
-				},
-				previewer: control.setting.previewer
-			} );
-			wp.customize.control.add( setting_id, widget_form_control );
-
-			// Make sure widget is removed from the other sidebars
-			wp.customize.each( function ( other_setting ) {
-				if ( other_setting.id === control.setting.id ) {
-					return;
-				}
-				if ( 0 !== other_setting.id.indexOf( 'sidebars_widgets[' ) ) {
-					return;
-				}
-				var other_sidebar_widgets = other_setting().slice(), i;
-				i = _.indexOf( other_sidebar_widgets, widget_id );
-				if ( -1 !== i ) {
-					other_sidebar_widgets.splice( i );
-					other_setting( other_sidebar_widgets );
-				}
-			} );
-
-			// Add widget to this sidebar
-			sidebar_widgets = control.setting().slice();
-			if ( -1 === _.indexOf( sidebar_widgets, widget_id ) ) {
-				sidebar_widgets.push( widget_id );
-				control.setting( sidebar_widgets );
-			}
-
-			customize_control.slideDown( function () {
-				if ( is_existing_widget ) {
-					widget_form_control.expandForm();
-					widget_form_control.updateWidget( {
-						instance: widget_form_control.setting(),
-						complete: function ( error ) {
-							if ( error ) {
-								throw error;
-							}
-							widget_form_control.focus();
-						}
-					} );
-				} else {
-					widget_form_control.focus();
-				}
-			} );
-
-			$( document ).trigger( 'widget-added', [ widget_el ] );
-
-			return widget_form_control;
-		}
-
-	} );
-
-	/**
 	 * Widget Form control
-	 * Note that 'widget_form' must match the Widget_Form_WP_Customize_Control::$type
+	 * Note that 'widget_form' must match the WP_Widget_Form_Customize_Control::$type
 	 */
-	customize.controlConstructor.widget_form = customize.Control.extend( {
-
+	api.Widgets.WidgetControl = api.Control.extend({
 		/**
 		 * Set up the control
 		 */
@@ -641,12 +161,14 @@
 		_setupModel: function () {
 			var control = this, remember_saved_widget_id;
 
+			api.Widgets.savedWidgetIds = api.Widgets.savedWidgetIds || [];
+
 			// Remember saved widgets so we know which to trash (move to inactive widgets sidebar)
 			remember_saved_widget_id = function () {
-				self.saved_widget_ids[control.params.widget_id] = true;
+				api.Widgets.savedWidgetIds[control.params.widget_id] = true;
 			};
-			wp.customize.bind( 'ready', remember_saved_widget_id );
-			wp.customize.bind( 'saved', remember_saved_widget_id );
+			api.bind( 'ready', remember_saved_widget_id );
+			api.bind( 'saved', remember_saved_widget_id );
 
 			control._update_count = 0;
 			control.is_widget_updating = false;
@@ -724,7 +246,7 @@
 			} );
 
 			// Reposition whenever a sidebar's widgets are changed
-			wp.customize.each( function ( setting ) {
+			api.each( function ( setting ) {
 				if ( 0 === setting.id.indexOf( 'sidebars_widgets[' ) ) {
 					setting.bind( function () {
 						if ( control.container.hasClass( 'expanded' ) ) {
@@ -805,10 +327,10 @@
 			/**
 			 * Add the widget reordering elements to the widget control
 			 */
-			control.container.find( '.widget-title-action' ).after( $( self.tpl.widget_reorder_nav ) );
+			control.container.find( '.widget-title-action' ).after( $( api.Widgets.data.tpl.widgetReorderNav ) );
 			move_widget_area = $(
-				_.template( self.tpl.move_widget_area, {
-					sidebars: _( self.registered_sidebars.toArray() ).pluck( 'attributes' )
+				_.template( api.Widgets.data.tpl.moveWidgetArea, {
+					sidebars: _( api.Widgets.registeredSidebars.toArray() ).pluck( 'attributes' )
 				} )
 			);
 			control.container.find( '.widget-top' ).after( move_widget_area );
@@ -827,7 +349,7 @@
 						sidebar_model;
 
 					sidebar_id = li.data( 'id' );
-					sidebar_model = self.registered_sidebars.get( sidebar_id );
+					sidebar_model = api.Widgets.registeredSidebars.get( sidebar_id );
 					li.toggle( sidebar_model.get( 'is_rendered' ) );
 					if ( li.hasClass( 'selected' ) && ! sidebar_model.get( 'is_rendered' ) ) {
 						select_sidebar_item( self_sidebar_item );
@@ -835,7 +357,7 @@
 				} );
 			};
 			update_available_sidebars();
-			self.registered_sidebars.on( 'change:is_rendered', update_available_sidebars );
+			api.Widgets.registeredSidebars.on( 'change:is_rendered', update_available_sidebars );
 
 			/**
 			 * Handle clicks for up/down/move on the reorder nav
@@ -893,8 +415,8 @@
 					new_sidebar_widget_ids,
 					i;
 
-				old_sidebar_widgets_setting = customize( 'sidebars_widgets[' + old_sidebar_id + ']' );
-				new_sidebar_widgets_setting = customize( 'sidebars_widgets[' + new_sidebar_id + ']' );
+				old_sidebar_widgets_setting = api( 'sidebars_widgets[' + old_sidebar_id + ']' );
+				new_sidebar_widgets_setting = api( 'sidebars_widgets[' + new_sidebar_id + ']' );
 				old_sidebar_widget_ids = Array.prototype.slice.call( old_sidebar_widgets_setting() );
 				new_sidebar_widget_ids = Array.prototype.slice.call( new_sidebar_widgets_setting() );
 
@@ -947,8 +469,8 @@
 
 			// Configure update button
 			save_btn = control.container.find( '.widget-control-save' );
-			save_btn.val( self.i18n.save_btn_label );
-			save_btn.attr( 'title', self.i18n.save_btn_tooltip );
+			save_btn.val( l10n.saveBtnLabel );
+			save_btn.attr( 'title', l10n.saveBtnTooltip );
 			save_btn.removeClass( 'button-primary' ).addClass( 'button-secondary' );
 			save_btn.on( 'click', function ( e ) {
 				e.preventDefault();
@@ -983,19 +505,19 @@
 			control.setting.previewer.channel.bind( 'synced', function () {
 				control.container.removeClass( 'previewer-loading' );
 			} );
-			self.previewer.bind( 'widget-updated', function ( updated_widget_id ) {
+			api.Widgets.Previewer.bind( 'widget-updated', function ( updated_widget_id ) {
 				if ( updated_widget_id === control.params.widget_id ) {
 					control.container.removeClass( 'previewer-loading' );
 				}
 			} );
 
 			// Update widget control to indicate whether it is currently rendered (cf. Widget Visibility)
-			self.previewer.bind( 'rendered-widgets', function ( rendered_widgets ) {
+			api.Widgets.Previewer.bind( 'rendered-widgets', function ( rendered_widgets ) {
 				var is_rendered = !! rendered_widgets[control.params.widget_id];
 				control.container.toggleClass( 'widget-rendered', is_rendered );
 			} );
 
-			form_update_event_handler = builtin_form_sync_handlers[ control.params.widget_id_base ];
+			form_update_event_handler = api.Widgets.formSyncHandlers[ control.params.widget_id_base ];
 			if ( form_update_event_handler ) {
 				$( document ).on( 'widget-synced', function ( e, widget_el ) {
 					if ( widget_root.is( widget_el ) ) {
@@ -1030,7 +552,7 @@
 				}
 
 				control.container.slideUp( function() {
-					var sidebars_widgets_control = self.getSidebarWidgetControlContainingWidget( control.params.widget_id ),
+					var sidebars_widgets_control = api.Widgets.getSidebarWidgetControlContainingWidget( control.params.widget_id ),
 						sidebar_widget_ids,
 						i;
 
@@ -1049,11 +571,11 @@
 			} );
 
 			replace_delete_with_remove = function () {
-				remove_btn.text( self.i18n.remove_btn_label ); // wp_widget_control() outputs the link as "Delete"
-				remove_btn.attr( 'title', self.i18n.remove_btn_tooltip );
+				remove_btn.text( l10n.removeBtnLabel ); // wp_widget_control() outputs the link as "Delete"
+				remove_btn.attr( 'title', l10n.removeBtnTooltip );
 			};
 			if ( control.params.is_new ) {
-				wp.customize.bind( 'saved', replace_delete_with_remove );
+				api.bind( 'saved', replace_delete_with_remove );
 			} else {
 				replace_delete_with_remove();
 			}
@@ -1123,7 +645,7 @@
 			var control = this, setting_id, sidebar_widgets_control;
 
 			setting_id = 'sidebars_widgets[' + control.params.sidebar_id + ']';
-			sidebar_widgets_control = customize.control( setting_id );
+			sidebar_widgets_control = api.control( setting_id );
 			if ( ! sidebar_widgets_control ) {
 				throw new Error( 'Unable to locate sidebar_widgets control for ' + control.params.sidebar_id );
 			}
@@ -1173,7 +695,7 @@
 
 			control.container.addClass( 'widget-form-loading' );
 			control.container.addClass( 'previewer-loading' );
-			processing = wp.customize.state( 'processing' );
+			processing = api.state( 'processing' );
 			processing( processing() + 1 );
 
 			if ( ! control.live_update_mode ) {
@@ -1183,7 +705,7 @@
 			params = {};
 			params.action = 'update-widget';
 			params.wp_customize = 'on';
-			params.nonce = self.nonce;
+			params.nonce = api.Widgets.data.nonce;
 
 			data = $.param( params );
 			inputs = control._getInputs( widget_content );
@@ -1213,17 +735,17 @@
 
 				// Check if the user is logged out.
 				if ( '0' === r ) {
-					self.previewer.preview.iframe.hide();
-					self.previewer.login().done( function() {
+					api.Widgets.Previewer.preview.iframe.hide();
+					api.Widgets.Previewer.login().done( function() {
 						control.updateWidget( args );
-						self.previewer.preview.iframe.show();
+						api.Widgets.Previewer.preview.iframe.show();
 					} );
 					return;
 				}
 
 				// Check for cheaters.
 				if ( '-1' === r ) {
-					self.previewer.cheatin();
+					api.Widgets.Previewer.cheatin();
 					return;
 				}
 
@@ -1294,7 +816,7 @@
 						complete_callback.call( control, null, { no_change: ! is_changed, ajax_finished: true } );
 					}
 				} else {
-					message = self.i18n.error;
+					message = l10n.error;
 					if ( r.data && r.data.message ) {
 						message = r.data.message;
 					}
@@ -1366,7 +888,7 @@
 
 			if ( do_expand ) {
 				// Close all other widget controls before expanding this one
-				wp.customize.control.each( function ( other_control ) {
+				api.control.each( function ( other_control ) {
 					if ( control.params.type === other_control.params.type && control !== other_control ) {
 						other_control.collapseForm();
 					}
@@ -1521,12 +1043,467 @@
 	} );
 
 	/**
+	 * Sidebar Widgets control
+	 * Note that 'sidebar_widgets' must match the WP_Widget_Area_Customize_Control::$type
+	 */
+	api.Widgets.SidebarControl = api.Control.extend({
+		/**
+		 * Set up the control
+		 */
+		ready: function() {
+			var control = this;
+			control.control_section = control.container.closest( '.control-section' );
+			control.section_content = control.container.closest( '.accordion-section-content' );
+			control._setupModel();
+			control._setupSortable();
+			control._setupAddition();
+			control._applyCardinalOrderClassNames();
+		},
+
+		/**
+		 * Update ordering of widget control forms when the setting is updated
+		 */
+		_setupModel: function() {
+			var control = this,
+				registered_sidebar = api.Widgets.registeredSidebars.get( control.params.sidebar_id );
+
+			control.setting.bind( function( new_widget_ids, old_widget_ids ) {
+				var widget_form_controls,
+					sidebar_widgets_add_control,
+					final_control_containers,
+					removed_widget_ids = _( old_widget_ids ).difference( new_widget_ids );
+
+				// Filter out any persistent widget_ids for widgets which have been deactivated
+				new_widget_ids = _( new_widget_ids ).filter( function ( new_widget_id ) {
+					var parsed_widget_id = parse_widget_id( new_widget_id );
+					return !! api.Widgets.availableWidgets.findWhere( { id_base: parsed_widget_id.id_base } );
+				} );
+
+				widget_form_controls = _( new_widget_ids ).map( function ( widget_id ) {
+					var widget_form_control = api.Widgets.getWidgetFormControlForWidget( widget_id );
+					if ( ! widget_form_control ) {
+						widget_form_control = control.addWidget( widget_id );
+					}
+					return widget_form_control;
+				} );
+
+				// Sort widget controls to their new positions
+				widget_form_controls.sort( function ( a, b ) {
+					var a_index = _.indexOf( new_widget_ids, a.params.widget_id ),
+						b_index = _.indexOf( new_widget_ids, b.params.widget_id );
+					if ( a_index === b_index ) {
+						return 0;
+					}
+					return a_index < b_index ? -1 : 1;
+				} );
+
+				sidebar_widgets_add_control = control.section_content.find( '.customize-control-sidebar_widgets' );
+
+				// Append the controls to put them in the right order
+				final_control_containers = _( widget_form_controls ).map( function( widget_form_controls ) {
+					return widget_form_controls.container[0];
+				} );
+
+				// Re-sort widget form controls (including widgets form other sidebars newly moved here)
+				sidebar_widgets_add_control.before( final_control_containers );
+				control._applyCardinalOrderClassNames();
+
+				// If the widget was dragged into the sidebar, make sure the sidebar_id param is updated
+				_( widget_form_controls ).each( function ( widget_form_control ) {
+					widget_form_control.params.sidebar_id = control.params.sidebar_id;
+				} );
+
+				// Cleanup after widget removal
+				_( removed_widget_ids ).each( function ( removed_widget_id ) {
+
+					// Using setTimeout so that when moving a widget to another sidebar, the other sidebars_widgets settings get a chance to update
+					setTimeout( function() {
+						var is_present_in_another_sidebar = false,
+							removed_control,
+							was_dragged_to_another_sidebar,
+							inactive_widgets,
+							removed_id_base,
+							widget;
+
+						// Check if the widget is in another sidebar
+						api.each( function ( other_setting ) {
+							if ( other_setting.id === control.setting.id || 0 !== other_setting.id.indexOf( 'sidebars_widgets[' ) || other_setting.id === 'sidebars_widgets[wp_inactive_widgets]' ) {
+								return;
+							}
+							var other_sidebar_widgets = other_setting(), i;
+
+							i = _.indexOf( other_sidebar_widgets, removed_widget_id );
+							if ( -1 !== i ) {
+								is_present_in_another_sidebar = true;
+							}
+						} );
+
+						// If the widget is present in another sidebar, abort!
+						if ( is_present_in_another_sidebar ) {
+							return;
+						}
+
+						removed_control = api.Widgets.getWidgetFormControlForWidget( removed_widget_id );
+
+						// Detect if widget control was dragged to another sidebar
+						was_dragged_to_another_sidebar = (
+							removed_control &&
+							$.contains( document, removed_control.container[0] ) &&
+							! $.contains( control.section_content[0], removed_control.container[0] )
+						);
+
+						// Delete any widget form controls for removed widgets
+						if ( removed_control && ! was_dragged_to_another_sidebar ) {
+							api.control.remove( removed_control.id );
+							removed_control.container.remove();
+						}
+
+						// Move widget to inactive widgets sidebar (move it to trash) if has been previously saved
+						// This prevents the inactive widgets sidebar from overflowing with throwaway widgets
+						if ( api.Widgets.savedWidgetIds[removed_widget_id] ) {
+							inactive_widgets = api.value( 'sidebars_widgets[wp_inactive_widgets]' )().slice();
+							inactive_widgets.push( removed_widget_id );
+							api.value( 'sidebars_widgets[wp_inactive_widgets]' )( _( inactive_widgets ).unique() );
+						}
+
+						// Make old single widget available for adding again
+						removed_id_base = parse_widget_id( removed_widget_id ).id_base;
+						widget = api.Widgets.availableWidgets.findWhere( { id_base: removed_id_base } );
+						if ( widget && ! widget.get( 'is_multi' ) ) {
+							widget.set( 'is_disabled', false );
+						}
+					} );
+
+				} );
+			} );
+
+			// Update the model with whether or not the sidebar is rendered
+			api.Widgets.Previewer.bind( 'rendered-sidebars', function ( rendered_sidebars ) {
+				var is_rendered = !! rendered_sidebars[control.params.sidebar_id];
+				registered_sidebar.set( 'is_rendered', is_rendered );
+			} );
+
+			// Show the sidebar section when it becomes visible
+			registered_sidebar.on( 'change:is_rendered', function ( ) {
+				var section_selector = '#accordion-section-sidebar-widgets-' + this.get( 'id' ), section;
+				section = $( section_selector );
+				if ( this.get( 'is_rendered' ) ) {
+					section.stop().slideDown( function() {
+						$( this ).css( 'height', 'auto' ); // so that the .accordion-section-content won't overflow
+					} );
+				} else {
+					// Make sure that hidden sections get closed first
+					if ( section.hasClass( 'open' ) ) {
+						// it would be nice if accordionSwitch() in accordion.js was public
+						section.find( '.accordion-section-title' ).trigger( 'click' );
+					}
+					section.stop().slideUp();
+				}
+			} );
+		},
+
+		/**
+		 * Allow widgets in sidebar to be re-ordered, and for the order to be previewed
+		 */
+		_setupSortable: function() {
+			var control = this;
+			control.is_reordering = false;
+
+			/**
+			 * Update widget order setting when controls are re-ordered
+			 */
+			control.section_content.sortable( {
+				items: '> .customize-control-widget_form',
+				handle: '.widget-top',
+				axis: 'y',
+				connectWith: '.accordion-section-content:has(.customize-control-sidebar_widgets)',
+				update: function() {
+					var widget_container_ids = control.section_content.sortable( 'toArray' ), widget_ids;
+					widget_ids = $.map( widget_container_ids, function ( widget_container_id ) {
+						return $( '#' + widget_container_id ).find( ':input[name=widget-id]' ).val();
+					} );
+					control.setting( widget_ids );
+				}
+			} );
+
+			/**
+			 * Expand other customizer sidebar section when dragging a control widget over it,
+			 * allowing the control to be dropped into another section
+			 */
+			control.control_section.find( '.accordion-section-title' ).droppable( {
+				accept: '.customize-control-widget_form',
+				over: function() {
+					if ( ! control.control_section.hasClass( 'open' ) ) {
+						control.control_section.addClass( 'open' );
+						control.section_content.toggle( false ).slideToggle( 150, function() {
+							control.section_content.sortable( 'refreshPositions' );
+						} );
+					}
+				}
+			} );
+
+			/**
+			 * Keyboard-accessible reordering
+			 */
+			control.container.find( '.reorder-toggle' ).on( 'click keydown', function( event ) {
+				if ( event.type === 'keydown' && ! ( event.which === 13 || event.which === 32 ) ) { // Enter or Spacebar
+					return;
+				}
+
+				control.toggleReordering( ! control.is_reordering );
+			} );
+		},
+
+		/**
+		 * Set up UI for adding a new widget
+		 */
+		_setupAddition: function() {
+			var control = this;
+
+			control.container.find( '.add-new-widget' ).on( 'click keydown', function( event ) {
+				if ( event.type === 'keydown' && ! ( event.which === 13 || event.which === 32 ) ) { // Enter or Spacebar
+					return;
+				}
+
+				if ( control.section_content.hasClass( 'reordering' ) ) {
+					return;
+				}
+
+				// @todo Use an control.is_adding state
+				if ( ! $( 'body' ).hasClass( 'adding-widget' ) ) {
+					api.Widgets.availableWidgetsPanel.open( control );
+				} else {
+					api.Widgets.availableWidgetsPanel.close();
+				}
+			} );
+		},
+
+		/**
+		 * Add classes to the widget_form controls to assist with styling
+		 */
+		_applyCardinalOrderClassNames: function() {
+			var control = this;
+			control.section_content.find( '.customize-control-widget_form' )
+				.removeClass( 'first-widget' )
+				.removeClass( 'last-widget' )
+				.find( '.move-widget-down, .move-widget-up' ).prop( 'tabIndex', 0 );
+
+			control.section_content.find( '.customize-control-widget_form:first' )
+				.addClass( 'first-widget' )
+				.find( '.move-widget-up' ).prop( 'tabIndex', -1 );
+			control.section_content.find( '.customize-control-widget_form:last' )
+				.addClass( 'last-widget' )
+				.find( '.move-widget-down' ).prop( 'tabIndex', -1 );
+		},
+
+
+		/***********************************************************************
+		 * Begin public API methods
+		 **********************************************************************/
+
+		/**
+		 * Enable/disable the reordering UI
+		 *
+		 * @param {Boolean} toggle to enable/disable reordering
+		 */
+		toggleReordering: function ( toggle ) {
+			var control = this;
+			toggle = Boolean( toggle );
+			if ( toggle === control.section_content.hasClass( 'reordering' ) ) {
+				return;
+			}
+
+			control.is_reordering = toggle;
+			control.section_content.toggleClass( 'reordering', toggle );
+
+			if ( toggle ) {
+				_( control.getWidgetFormControls() ).each( function ( form_control ) {
+					form_control.collapseForm();
+				} );
+			}
+		},
+
+		/**
+		 * @return {wp.customize.controlConstructor.widget_form[]}
+		 */
+		getWidgetFormControls: function() {
+			var control = this, form_controls;
+
+			form_controls = _( control.setting() ).map( function ( widget_id ) {
+				var setting_id = widget_id_to_setting_id( widget_id ),
+					form_control = api.control( setting_id );
+
+				if ( ! form_control ) {
+					throw new Error( 'Unable to find widget_form control for ' + widget_id );
+				}
+				return form_control;
+			} );
+			return form_controls;
+		},
+
+		/**
+		 * @param {string} widget_id or an id_base for adding a previously non-existing widget
+		 * @returns {object} widget_form control instance
+		 */
+		addWidget: function ( widget_id ) {
+			var control = this,
+				control_html,
+				widget_el,
+				customize_control_type = 'widget_form',
+				customize_control,
+				parsed_widget_id = parse_widget_id( widget_id ),
+				widget_number = parsed_widget_id.number,
+				widget_id_base = parsed_widget_id.id_base,
+				widget = api.Widgets.availableWidgets.findWhere( {id_base: widget_id_base} ),
+				setting_id,
+				is_existing_widget,
+				Constructor,
+				widget_form_control,
+				sidebar_widgets,
+				setting_args;
+
+			if ( ! widget ) {
+				throw new Error( 'Widget unexpectedly not found.' );
+			}
+			if ( widget_number && ! widget.get( 'is_multi' ) ) {
+				throw new Error( 'Did not expect a widget number to be supplied for a non-multi widget' );
+			}
+
+			// Set up new multi widget
+			if ( widget.get( 'is_multi' ) && ! widget_number ) {
+				widget.set( 'multi_number', widget.get( 'multi_number' ) + 1 );
+				widget_number = widget.get( 'multi_number' );
+			}
+
+			control_html = $( '#widget-tpl-' + widget.get( 'id' ) ).html();
+			if ( widget.get( 'is_multi' ) ) {
+				control_html = control_html.replace( /<[^<>]+>/g, function ( m ) {
+					return m.replace( /__i__|%i%/g, widget_number );
+				} );
+			} else {
+				widget.set( 'is_disabled', true ); // Prevent single widget from being added again now
+			}
+			widget_el = $( control_html );
+
+			customize_control = $( '<li></li>' );
+			customize_control.addClass( 'customize-control' );
+			customize_control.addClass( 'customize-control-' + customize_control_type );
+			customize_control.append( widget_el );
+			customize_control.find( '> .widget-icon' ).remove();
+			if ( widget.get( 'is_multi' ) ) {
+				customize_control.find( 'input[name="widget_number"]' ).val( widget_number );
+				customize_control.find( 'input[name="multi_number"]' ).val( widget_number );
+			}
+			widget_id = customize_control.find( '[name="widget-id"]' ).val();
+			customize_control.hide(); // to be slid-down below
+
+			setting_id = 'widget_' + widget.get( 'id_base' );
+			if ( widget.get( 'is_multi' ) ) {
+				setting_id += '[' + widget_number + ']';
+			}
+			customize_control.attr( 'id', 'customize-control-' + setting_id.replace( /\]/g, '' ).replace( /\[/g, '-' ) );
+
+			control.container.after( customize_control );
+
+			// Only create setting if it doesn't already exist (if we're adding a pre-existing inactive widget)
+			is_existing_widget = api.has( setting_id );
+			if ( ! is_existing_widget ) {
+				setting_args = {
+					transport: 'refresh',
+					previewer: control.setting.previewer
+				};
+				api.create( setting_id, setting_id, {}, setting_args );
+			}
+
+			Constructor = api.controlConstructor[customize_control_type];
+			widget_form_control = new Constructor( setting_id, {
+				params: {
+					settings: {
+						'default': setting_id
+					},
+					sidebar_id: control.params.sidebar_id,
+					widget_id: widget_id,
+					widget_id_base: widget.get( 'id_base' ),
+					type: customize_control_type,
+					is_new: ! is_existing_widget,
+					width: widget.get( 'width' ),
+					height: widget.get( 'height' ),
+					is_wide: widget.get( 'is_wide' )
+				},
+				previewer: control.setting.previewer
+			} );
+			api.control.add( setting_id, widget_form_control );
+
+			// Make sure widget is removed from the other sidebars
+			api.each( function ( other_setting ) {
+				if ( other_setting.id === control.setting.id ) {
+					return;
+				}
+				if ( 0 !== other_setting.id.indexOf( 'sidebars_widgets[' ) ) {
+					return;
+				}
+				var other_sidebar_widgets = other_setting().slice(), i;
+				i = _.indexOf( other_sidebar_widgets, widget_id );
+				if ( -1 !== i ) {
+					other_sidebar_widgets.splice( i );
+					other_setting( other_sidebar_widgets );
+				}
+			} );
+
+			// Add widget to this sidebar
+			sidebar_widgets = control.setting().slice();
+			if ( -1 === _.indexOf( sidebar_widgets, widget_id ) ) {
+				sidebar_widgets.push( widget_id );
+				control.setting( sidebar_widgets );
+			}
+
+			customize_control.slideDown( function() {
+				if ( is_existing_widget ) {
+					widget_form_control.expandForm();
+					widget_form_control.updateWidget( {
+						instance: widget_form_control.setting(),
+						complete: function ( error ) {
+							if ( error ) {
+								throw error;
+							}
+							widget_form_control.focus();
+						}
+					} );
+				} else {
+					widget_form_control.focus();
+				}
+			} );
+
+			$( document ).trigger( 'widget-added', [ widget_el ] );
+
+			return widget_form_control;
+		}
+
+	} );
+
+	$.extend( api.controlConstructor, {
+		widget_form: api.Widgets.WidgetControl,
+		sidebar_widgets: api.Widgets.SidebarControl
+	});
+
+	api.bind( 'ready', function() {
+		// Set up the widgets panel
+		api.Widgets.availableWidgetsPanel.setup();
+
+		// Highlight widget control
+		api.Widgets.Previewer.bind( 'highlight-widget-control', api.Widgets.highlightWidgetFormControl );
+
+		// Open and focus widget control
+		api.Widgets.Previewer.bind( 'focus-widget-control', api.Widgets.focusWidgetFormControl );
+	} );
+
+	/**
 	 * Capture the instance of the Previewer since it is private
 	 */
-	OldPreviewer = wp.customize.Previewer;
-	wp.customize.Previewer = OldPreviewer.extend( {
+	OldPreviewer = api.Previewer;
+	api.Previewer = OldPreviewer.extend({
 		initialize: function( params, options ) {
-			self.previewer = this;
+			api.Widgets.Previewer = this;
 			OldPreviewer.prototype.initialize.call( this, params, options );
 			this.bind( 'refresh', this.refresh );
 		}
@@ -1537,8 +1514,8 @@
 	 *
 	 * @param {string} widgetId
 	 */
-	self.highlightWidgetFormControl = function( widgetId ) {
-		var control = self.getWidgetFormControlForWidget( widgetId );
+	api.Widgets.highlightWidgetFormControl = function( widgetId ) {
+		var control = api.Widgets.getWidgetFormControlForWidget( widgetId );
 
 		if ( control ) {
 			control.highlightSectionAndControl();
@@ -1550,8 +1527,8 @@
 	 *
 	 * @param {string} widgetId
 	 */
-	self.focusWidgetFormControl = function( widgetId ) {
-		var control = self.getWidgetFormControlForWidget( widgetId );
+	api.Widgets.focusWidgetFormControl = function( widgetId ) {
+		var control = api.Widgets.getWidgetFormControlForWidget( widgetId );
 
 		if ( control ) {
 			control.focus();
@@ -1563,14 +1540,15 @@
 	 * @param {string} widget_id
 	 * @return {object|null}
 	 */
-	self.getSidebarWidgetControlContainingWidget = function ( widget_id ) {
+	api.Widgets.getSidebarWidgetControlContainingWidget = function ( widget_id ) {
 		var found_control = null;
 		// @todo this can use widget_id_to_setting_id(), then pass into wp.customize.control( x ).getSidebarWidgetsControl()
-		wp.customize.control.each( function ( control ) {
+		api.control.each( function ( control ) {
 			if ( control.params.type === 'sidebar_widgets' && -1 !== _.indexOf( control.setting(), widget_id ) ) {
 				found_control = control;
 			}
 		} );
+
 		return found_control;
 	};
 
@@ -1579,28 +1557,22 @@
 	 * @param {string} widget_id
 	 * @return {object|null}
 	 */
-	self.getWidgetFormControlForWidget = function ( widget_id ) {
+	api.Widgets.getWidgetFormControlForWidget = function ( widget_id ) {
 		var found_control = null;
 		// @todo We can just use widget_id_to_setting_id() here
-		wp.customize.control.each( function ( control ) {
+		api.control.each( function ( control ) {
 			if ( control.params.type === 'widget_form' && control.params.widget_id === widget_id ) {
 				found_control = control;
 			}
 		} );
+
 		return found_control;
 	};
 
 	/**
-	 * @returns {Window}
-	 */
-	self.getPreviewWindow = function (){
-		return $( '#customize-preview' ).find( 'iframe' ).prop( 'contentWindow' );
-	};
-
-	/**
 	 * Available Widgets Panel
 	 */
-	self.availableWidgetsPanel = {
+	api.Widgets.availableWidgetsPanel = {
 		active_sidebar_widgets_control: null,
 		selected_widget_tpl: null,
 		container: null,
@@ -1615,7 +1587,7 @@
 			panel.container = $( '#available-widgets' );
 			panel.filter_input = $( '#available-widgets-filter' ).find( 'input' );
 
-			self.available_widgets.on( 'change update', panel.update_available_widgets_list );
+			api.Widgets.availableWidgets.on( 'change update', panel.update_available_widgets_list );
 			panel.update_available_widgets_list();
 
 			// If the available widgets panel is open and the customize controls are
@@ -1629,7 +1601,7 @@
 			} );
 
 			// Close the panel if the URL in the preview changes
-			self.previewer.bind( 'url', function () {
+			api.Widgets.Previewer.bind( 'url', function() {
 				panel.close();
 			} );
 
@@ -1647,7 +1619,7 @@
 			panel.filter_input.on( 'input keyup change', function( event ) {
 				var first_visible_widget;
 
-				self.available_widgets.doSearch( event.target.value );
+				api.Widgets.availableWidgets.doSearch( event.target.value );
 
 				// Remove a widget from being selected if it is no longer visible
 				if ( panel.selected_widget_tpl && ! panel.selected_widget_tpl.is( ':visible' ) ) {
@@ -1725,13 +1697,13 @@
 		 * Updates widgets list.
 		 */
 		update_available_widgets_list: function() {
-			var panel = self.availableWidgetsPanel;
+			var panel = api.Widgets.availableWidgetsPanel;
 
 			// First hide all widgets...
 			panel.container.find( '.widget-tpl' ).hide();
 
 			// ..and then show only available widgets which could be filtered
-			self.available_widgets.each( function ( widget ) {
+			api.Widgets.availableWidgets.each( function ( widget ) {
 				var widget_tpl = $( '#widget-tpl-' + widget.id );
 				widget_tpl.toggle( ! widget.get( 'is_disabled' ) );
 				if ( widget.get( 'is_disabled' ) && widget_tpl.is( panel.selected_widget_tpl ) ) {
@@ -1761,7 +1733,7 @@
 			panel.select( widget_tpl );
 
 			widget_id = $( panel.selected_widget_tpl ).data( 'widget-id' );
-			widget = self.available_widgets.findWhere( {id: widget_id} );
+			widget = api.Widgets.availableWidgets.findWhere( {id: widget_id} );
 			if ( ! widget ) {
 				throw new Error( 'Widget unexpectedly not found.' );
 			}
@@ -1785,7 +1757,7 @@
 
 			$( 'body' ).addClass( 'adding-widget' );
 			panel.container.find( '.widget-tpl' ).removeClass( 'selected' );
-			self.available_widgets.doSearch( '' );
+			api.Widgets.availableWidgets.doSearch( '' );
 			panel.filter_input.focus();
 		},
 
@@ -1839,5 +1811,4 @@
 		return setting_id;
 	}
 
-	return self;
-}( jQuery ));
+})( window.wp, jQuery );
Index: src/wp-includes/class-wp-customize-control.php
===================================================================
--- src/wp-includes/class-wp-customize-control.php	(revision 27974)
+++ src/wp-includes/class-wp-customize-control.php	(working copy)
@@ -917,12 +917,12 @@
 	public function render_content() {
 		?>
 		<span class="button-secondary add-new-widget" tabindex="0">
-			<?php esc_html_e( 'Add a Widget' ); ?>
+			<?php _e( 'Add a Widget' ); ?>
 		</span>
 
 		<span class="reorder-toggle" tabindex="0">
-			<span class="reorder"><?php esc_html_e( 'Reorder' ); ?></span>
-			<span class="reorder-done"><?php esc_html_e( 'Done' ); ?></span>
+			<span class="reorder"><?php _ex( 'Reorder', 'Reorder widgets in Customizer' ); ?></span>
+			<span class="reorder-done"><?php _ex( 'Done', 'Cancel reordering widgets in Customizer'  ); ?></span>
 		</span>
 		<?php
 	}
@@ -940,11 +940,10 @@
 	public $width;
 	public $height;
 	public $is_wide = false;
-	public $is_live_previewable = false;
 
 	public function to_json() {
 		parent::to_json();
-		$exported_properties = array( 'widget_id', 'widget_id_base', 'sidebar_id', 'width', 'height', 'is_wide', 'is_live_previewable' );
+		$exported_properties = array( 'widget_id', 'widget_id_base', 'sidebar_id', 'width', 'height', 'is_wide' );
 		foreach ( $exported_properties as $key ) {
 			$this->json[ $key ] = $this->$key;
 		}
Index: src/wp-includes/class-wp-customize-widgets.php
===================================================================
--- src/wp-includes/class-wp-customize-widgets.php	(revision 27974)
+++ src/wp-includes/class-wp-customize-widgets.php	(working copy)
@@ -406,8 +406,6 @@
 				$setting_id        = $this->get_setting_id( $widget_id );
 				$id_base           = $GLOBALS['wp_registered_widget_controls'][$widget_id]['id_base'];
 
-				assert( false !== is_active_widget( $registered_widget['callback'], $registered_widget['id'], false, false ) );
-
 				$control = new WP_Widget_Form_Customize_Control( $this->manager, $setting_id, array(
 					'label'          => $registered_widget['name'],
 					'section'        => $section_id,
@@ -600,7 +598,7 @@
 			array( '{description}', '{btn}' ),
 			array(
 				( 'Select an area to move this widget into:' ), // @todo translate
-				esc_html_x( 'Move', 'move widget' ),
+				_x( 'Move', 'move widget' ),
 			),
 			'<div class="move-widget-area">
 				<p class="description">{description}</p>
@@ -615,39 +613,34 @@
 			</div>'
 		);
 
-		/*
-		 * Why not wp_localize_script? Because we're not localizing,
-		 * and it forces values into strings.
-		 */
 		global $wp_scripts;
 
-		$exports = array(
+		$settings = array(
 			'nonce'               => wp_create_nonce( 'update-widget' ),
-			'registered_sidebars' => array_values( $GLOBALS['wp_registered_sidebars'] ),
-			'registered_widgets'  => $GLOBALS['wp_registered_widgets'],
-			'available_widgets'   => $available_widgets, // @todo Merge this with registered_widgets
-			'i18n' => array(
-				'save_btn_label'     => __( 'Apply' ),
-				// @todo translate? do we want these tooltips?
-				'save_btn_tooltip'   => ( 'Save and preview changes before publishing them.' ),
-				'remove_btn_label'   => __( 'Remove' ),
-				'remove_btn_tooltip' => ( 'Trash widget by moving it to the inactive widgets sidebar.' ),
+			'registeredSidebars'   => array_values( $GLOBALS['wp_registered_sidebars'] ),
+			'registeredWidgets'    => $GLOBALS['wp_registered_widgets'],
+			'availableWidgets'     => $available_widgets, // @todo Merge this with registered_widgets
+			'l10n' => array(
+				'saveBtnLabel'     => __( 'Apply' ),
+				'saveBtnTooltip'   => __( 'Save and preview changes before publishing them.' ),
+				'removeBtnLabel'   => __( 'Remove' ),
+				'removeBtnTooltip' => __( 'Trash widget by moving it to the inactive widgets sidebar.' ),
 				'error'              => __( 'An error has occurred. Please reload the page and try again.' ),
 			),
 			'tpl'                 => array(
-				'widget_reorder_nav' => $widget_reorder_nav_tpl,
-				'move_widget_area'   => $move_widget_area_tpl,
+				'widgetReorderNav' => $widget_reorder_nav_tpl,
+				'moveWidgetArea'   => $move_widget_area_tpl,
 			),
 		);
 
-		foreach ( $exports['registered_widgets'] as &$registered_widget ) {
+		foreach ( $settings['registeredWidgets'] as &$registered_widget ) {
 			unset( $registered_widget['callback'] ); // may not be JSON-serializeable
 		}
 
 		$wp_scripts->add_data(
 			'customize-widgets',
 			'data',
-			sprintf( 'var WidgetCustomizer_exports = %s;', json_encode( $exports ) )
+			sprintf( 'var _wpCustomizeWidgetsSettings = %s;', json_encode( $settings ) )
 		);
 	}
 
Index: src/wp-includes/js/customize-preview-widgets.js
===================================================================
--- src/wp-includes/js/customize-preview-widgets.js	(revision 27974)
+++ src/wp-includes/js/customize-preview-widgets.js	(working copy)
@@ -1,4 +1,4 @@
-(function( $, wp ){
+(function( wp, $ ){
 
 	if ( ! wp || ! wp.customize ) { return; }
 
@@ -124,4 +124,4 @@
 		api.WidgetCustomizerPreview.init();
 	});
 
-})( jQuery, window.wp );
+})( window.wp, jQuery );
