wp/wp-admin/js/widgets.js
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 /*global ajaxurl, isRtl */
     1 /*global ajaxurl, isRtl */
     2 var wpWidgets;
     2 var wpWidgets;
     3 (function($) {
     3 (function($) {
       
     4 	var $document = $( document );
     4 
     5 
     5 wpWidgets = {
     6 wpWidgets = {
       
     7 	/**
       
     8 	 * A closed Sidebar that gets a Widget dragged over it.
       
     9 	 *
       
    10 	 * @var {element|null}
       
    11 	 */
       
    12 	hoveredSidebar: null,
       
    13 
       
    14 	/**
       
    15 	 * Translations.
       
    16 	 *
       
    17 	 * Exported from PHP in wp_default_scripts().
       
    18 	 *
       
    19 	 * @var {object}
       
    20 	 */
       
    21 	l10n: {
       
    22 		save: '{save}',
       
    23 		saved: '{saved}',
       
    24 		saveAlert: '{saveAlert}'
       
    25 	},
       
    26 
       
    27 	/**
       
    28 	 * Lookup of which widgets have had change events triggered.
       
    29 	 *
       
    30 	 * @var {object}
       
    31 	 */
       
    32 	dirtyWidgets: {},
     6 
    33 
     7 	init : function() {
    34 	init : function() {
     8 		var rem, the_id,
    35 		var rem, the_id,
     9 			self = this,
    36 			self = this,
    10 			chooser = $('.widgets-chooser'),
    37 			chooser = $('.widgets-chooser'),
    11 			selectSidebar = chooser.find('.widgets-chooser-sidebars'),
    38 			selectSidebar = chooser.find('.widgets-chooser-sidebars'),
    12 			sidebars = $('div.widgets-sortables'),
    39 			sidebars = $('div.widgets-sortables'),
    13 			isRTL = !! ( 'undefined' !== typeof isRtl && isRtl );
    40 			isRTL = !! ( 'undefined' !== typeof isRtl && isRtl );
    14 
    41 
    15 		$('#widgets-right .sidebar-name').click( function() {
    42 		// Handle the widgets containers in the right column.
    16 			var $this = $(this),
    43 		$( '#widgets-right .sidebar-name' )
    17 				$wrap = $this.closest('.widgets-holder-wrap');
    44 			/*
    18 
    45 			 * Toggle the widgets containers when clicked and update the toggle
    19 			if ( $wrap.hasClass('closed') ) {
    46 			 * button `aria-expanded` attribute value.
    20 				$wrap.removeClass('closed');
    47 			 */
    21 				$this.parent().sortable('refresh');
    48 			.click( function() {
    22 			} else {
    49 				var $this = $( this ),
    23 				$wrap.addClass('closed');
    50 					$wrap = $this.closest( '.widgets-holder-wrap '),
    24 			}
    51 					$toggle = $this.find( '.handlediv' );
    25 		});
    52 
    26 
    53 				if ( $wrap.hasClass( 'closed' ) ) {
    27 		$('#widgets-left .sidebar-name').click( function() {
    54 					$wrap.removeClass( 'closed' );
    28 			$(this).closest('.widgets-holder-wrap').toggleClass('closed');
    55 					$toggle.attr( 'aria-expanded', 'true' );
       
    56 					// Refresh the jQuery UI sortable items.
       
    57 					$this.parent().sortable( 'refresh' );
       
    58 				} else {
       
    59 					$wrap.addClass( 'closed' );
       
    60 					$toggle.attr( 'aria-expanded', 'false' );
       
    61 				}
       
    62 
       
    63 				// Update the admin menu "sticky" state.
       
    64 				$document.triggerHandler( 'wp-pin-menu' );
       
    65 			})
       
    66 			/*
       
    67 			 * Set the initial `aria-expanded` attribute value on the widgets
       
    68 			 * containers toggle button. The first one is expanded by default.
       
    69 			 */
       
    70 			.find( '.handlediv' ).each( function( index ) {
       
    71 				if ( 0 === index ) {
       
    72 					// jQuery equivalent of `continue` within an `each()` loop.
       
    73 					return;
       
    74 				}
       
    75 
       
    76 				$( this ).attr( 'aria-expanded', 'false' );
       
    77 			});
       
    78 
       
    79 		// Show AYS dialog when there are unsaved widget changes.
       
    80 		$( window ).on( 'beforeunload.widgets', function( event ) {
       
    81 			var dirtyWidgetIds = [], unsavedWidgetsElements;
       
    82 			$.each( self.dirtyWidgets, function( widgetId, dirty ) {
       
    83 				if ( dirty ) {
       
    84 					dirtyWidgetIds.push( widgetId );
       
    85 				}
       
    86 			});
       
    87 			if ( 0 !== dirtyWidgetIds.length ) {
       
    88 				unsavedWidgetsElements = $( '#widgets-right' ).find( '.widget' ).filter( function() {
       
    89 					return -1 !== dirtyWidgetIds.indexOf( $( this ).prop( 'id' ).replace( /^widget-\d+_/, '' ) );
       
    90 				});
       
    91 				unsavedWidgetsElements.each( function() {
       
    92 					if ( ! $( this ).hasClass( 'open' ) ) {
       
    93 						$( this ).find( '.widget-title-action:first' ).click();
       
    94 					}
       
    95 				});
       
    96 
       
    97 				// Bring the first unsaved widget into view and focus on the first tabbable field.
       
    98 				unsavedWidgetsElements.first().each( function() {
       
    99 					if ( this.scrollIntoViewIfNeeded ) {
       
   100 						this.scrollIntoViewIfNeeded();
       
   101 					} else {
       
   102 						this.scrollIntoView();
       
   103 					}
       
   104 					$( this ).find( '.widget-inside :tabbable:first' ).focus();
       
   105 				} );
       
   106 
       
   107 				event.returnValue = wpWidgets.l10n.saveAlert;
       
   108 				return event.returnValue;
       
   109 			}
       
   110 		});
       
   111 
       
   112 		// Handle the widgets containers in the left column.
       
   113 		$( '#widgets-left .sidebar-name' ).click( function() {
       
   114 			var $wrap = $( this ).closest( '.widgets-holder-wrap' );
       
   115 
       
   116 			$wrap
       
   117 				.toggleClass( 'closed' )
       
   118 				.find( '.handlediv' ).attr( 'aria-expanded', ! $wrap.hasClass( 'closed' ) );
       
   119 
       
   120 			// Update the admin menu "sticky" state.
       
   121 			$document.triggerHandler( 'wp-pin-menu' );
    29 		});
   122 		});
    30 
   123 
    31 		$(document.body).bind('click.widgets-toggle', function(e) {
   124 		$(document.body).bind('click.widgets-toggle', function(e) {
    32 			var target = $(e.target),
   125 			var target = $(e.target),
    33 				css = { 'z-index': 100 },
   126 				css = { 'z-index': 100 },
    34 				widget, inside, targetWidth, widgetWidth, margin;
   127 				widget, inside, targetWidth, widgetWidth, margin, saveButton, widgetId,
       
   128 				toggleBtn = target.closest( '.widget' ).find( '.widget-top button.widget-action' );
    35 
   129 
    36 			if ( target.parents('.widget-top').length && ! target.parents('#available-widgets').length ) {
   130 			if ( target.parents('.widget-top').length && ! target.parents('#available-widgets').length ) {
    37 				widget = target.closest('div.widget');
   131 				widget = target.closest('div.widget');
    38 				inside = widget.children('.widget-inside');
   132 				inside = widget.children('.widget-inside');
    39 				targetWidth = parseInt( widget.find('input.widget-width').val(), 10 ),
   133 				targetWidth = parseInt( widget.find('input.widget-width').val(), 10 );
    40 				widgetWidth = widget.parent().width();
   134 				widgetWidth = widget.parent().width();
       
   135 				widgetId = inside.find( '.widget-id' ).val();
       
   136 
       
   137 				// Save button is initially disabled, but is enabled when a field is changed.
       
   138 				if ( ! widget.data( 'dirty-state-initialized' ) ) {
       
   139 					saveButton = inside.find( '.widget-control-save' );
       
   140 					saveButton.prop( 'disabled', true ).val( wpWidgets.l10n.saved );
       
   141 					inside.on( 'input change', function() {
       
   142 						self.dirtyWidgets[ widgetId ] = true;
       
   143 						widget.addClass( 'widget-dirty' );
       
   144 						saveButton.prop( 'disabled', false ).val( wpWidgets.l10n.save );
       
   145 					});
       
   146 					widget.data( 'dirty-state-initialized', true );
       
   147 				}
    41 
   148 
    42 				if ( inside.is(':hidden') ) {
   149 				if ( inside.is(':hidden') ) {
    43 					if ( targetWidth > 250 && ( targetWidth + 30 > widgetWidth ) && widget.closest('div.widgets-sortables').length ) {
   150 					if ( targetWidth > 250 && ( targetWidth + 30 > widgetWidth ) && widget.closest('div.widgets-sortables').length ) {
    44 						if ( widget.closest('div.widget-liquid-right').length ) {
   151 						if ( widget.closest('div.widget-liquid-right').length ) {
    45 							margin = isRTL ? 'margin-right' : 'margin-left';
   152 							margin = isRTL ? 'margin-right' : 'margin-left';
    48 						}
   155 						}
    49 
   156 
    50 						css[ margin ] = widgetWidth - ( targetWidth + 30 ) + 'px';
   157 						css[ margin ] = widgetWidth - ( targetWidth + 30 ) + 'px';
    51 						widget.css( css );
   158 						widget.css( css );
    52 					}
   159 					}
    53 					widget.addClass( 'open' );
   160 					/*
    54 					inside.slideDown('fast');
   161 					 * Don't change the order of attributes changes and animation:
       
   162 					 * it's important for screen readers, see ticket #31476.
       
   163 					 */
       
   164 					toggleBtn.attr( 'aria-expanded', 'true' );
       
   165 					inside.slideDown( 'fast', function() {
       
   166 						widget.addClass( 'open' );
       
   167 					});
    55 				} else {
   168 				} else {
    56 					inside.slideUp('fast', function() {
   169 					/*
       
   170 					 * Don't change the order of attributes changes and animation:
       
   171 					 * it's important for screen readers, see ticket #31476.
       
   172 					 */
       
   173 					toggleBtn.attr( 'aria-expanded', 'false' );
       
   174 					inside.slideUp( 'fast', function() {
    57 						widget.attr( 'style', '' );
   175 						widget.attr( 'style', '' );
    58 						widget.removeClass( 'open' );
   176 						widget.removeClass( 'open' );
    59 					});
   177 					});
    60 				}
   178 				}
    61 				e.preventDefault();
   179 				e.preventDefault();
    66 				wpWidgets.save( target.closest('div.widget'), 1, 1, 0 );
   184 				wpWidgets.save( target.closest('div.widget'), 1, 1, 0 );
    67 				e.preventDefault();
   185 				e.preventDefault();
    68 			} else if ( target.hasClass('widget-control-close') ) {
   186 			} else if ( target.hasClass('widget-control-close') ) {
    69 				widget = target.closest('div.widget');
   187 				widget = target.closest('div.widget');
    70 				widget.removeClass( 'open' );
   188 				widget.removeClass( 'open' );
       
   189 				toggleBtn.attr( 'aria-expanded', 'false' );
    71 				wpWidgets.close( widget );
   190 				wpWidgets.close( widget );
    72 				e.preventDefault();
   191 				e.preventDefault();
       
   192 			} else if ( target.attr( 'id' ) === 'inactive-widgets-control-remove' ) {
       
   193 				wpWidgets.removeInactiveWidgets();
       
   194 				e.preventDefault();
    73 			}
   195 			}
    74 		});
   196 		});
    75 
   197 
    76 		sidebars.children('.widget').each( function() {
   198 		sidebars.children('.widget').each( function() {
    77 			var $this = $(this);
   199 			var $this = $(this);
    78 
   200 
    79 			wpWidgets.appendTitle( this );
   201 			wpWidgets.appendTitle( this );
    80 
   202 
    81 			if ( $this.find( 'p.widget-error' ).length ) {
   203 			if ( $this.find( 'p.widget-error' ).length ) {
    82 				$this.find( 'a.widget-action' ).trigger('click');
   204 				$this.find( '.widget-action' ).trigger( 'click' ).attr( 'aria-expanded', 'true' );
    83 			}
   205 			}
    84 		});
   206 		});
    85 
   207 
    86 		$('#widget-list').children('.widget').draggable({
   208 		$('#widget-list').children('.widget').draggable({
    87 			connectToSortable: 'div.widgets-sortables',
   209 			connectToSortable: 'div.widgets-sortables',
    88 			handle: '> .widget-top > .widget-title',
   210 			handle: '> .widget-top > .widget-title',
    89 			distance: 2,
   211 			distance: 2,
    90 			helper: 'clone',
   212 			helper: 'clone',
    91 			zIndex: 100,
   213 			zIndex: 100,
    92 			containment: 'document',
   214 			containment: '#wpwrap',
       
   215 			refreshPositions: true,
    93 			start: function( event, ui ) {
   216 			start: function( event, ui ) {
    94 				var chooser = $(this).find('.widgets-chooser');
   217 				var chooser = $(this).find('.widgets-chooser');
    95 
   218 
    96 				ui.helper.find('div.widget-description').hide();
   219 				ui.helper.find('div.widget-description').hide();
    97 				the_id = this.id;
   220 				the_id = this.id;
   111 
   234 
   112 				rem = '';
   235 				rem = '';
   113 			}
   236 			}
   114 		});
   237 		});
   115 
   238 
       
   239 		/**
       
   240 		 * Opens and closes previously closed Sidebars when Widgets are dragged over/out of them.
       
   241 		 */
       
   242 		sidebars.droppable( {
       
   243 			tolerance: 'intersect',
       
   244 
       
   245 			/**
       
   246 			 * Open Sidebar when a Widget gets dragged over it.
       
   247 			 *
       
   248 			 * @param {object} event jQuery event object.
       
   249 			 */
       
   250 			over: function( event ) {
       
   251 				var $wrap = $( event.target ).parent();
       
   252 
       
   253 				if ( wpWidgets.hoveredSidebar && ! $wrap.is( wpWidgets.hoveredSidebar ) ) {
       
   254 					// Close the previous Sidebar as the Widget has been dragged onto another Sidebar.
       
   255 					wpWidgets.closeSidebar( event );
       
   256 				}
       
   257 
       
   258 				if ( $wrap.hasClass( 'closed' ) ) {
       
   259 					wpWidgets.hoveredSidebar = $wrap;
       
   260 					$wrap
       
   261 						.removeClass( 'closed' )
       
   262 						.find( '.handlediv' ).attr( 'aria-expanded', 'true' );
       
   263 				}
       
   264 
       
   265 				$( this ).sortable( 'refresh' );
       
   266 			},
       
   267 
       
   268 			/**
       
   269 			 * Close Sidebar when the Widget gets dragged out of it.
       
   270 			 *
       
   271 			 * @param {object} event jQuery event object.
       
   272 			 */
       
   273 			out: function( event ) {
       
   274 				if ( wpWidgets.hoveredSidebar ) {
       
   275 					wpWidgets.closeSidebar( event );
       
   276 				}
       
   277 			}
       
   278 		} );
       
   279 
   116 		sidebars.sortable({
   280 		sidebars.sortable({
   117 			placeholder: 'widget-placeholder',
   281 			placeholder: 'widget-placeholder',
   118 			items: '> .widget',
   282 			items: '> .widget',
   119 			handle: '> .widget-top > .widget-title',
   283 			handle: '> .widget-top > .widget-title',
   120 			cursor: 'move',
   284 			cursor: 'move',
   121 			distance: 2,
   285 			distance: 2,
   122 			containment: 'document',
   286 			containment: '#wpwrap',
       
   287 			tolerance: 'pointer',
       
   288 			refreshPositions: true,
   123 			start: function( event, ui ) {
   289 			start: function( event, ui ) {
   124 				var height, $this = $(this),
   290 				var height, $this = $(this),
   125 					$wrap = $this.parent(),
   291 					$wrap = $this.parent(),
   126 					inside = ui.item.children('.widget-inside');
   292 					inside = ui.item.children('.widget-inside');
   127 
   293 
   128 				if ( inside.css('display') === 'block' ) {
   294 				if ( inside.css('display') === 'block' ) {
       
   295 					ui.item.removeClass('open');
       
   296 					ui.item.find( '.widget-top button.widget-action' ).attr( 'aria-expanded', 'false' );
   129 					inside.hide();
   297 					inside.hide();
   130 					$(this).sortable('refreshPositions');
   298 					$(this).sortable('refreshPositions');
   131 				}
   299 				}
   132 
   300 
   133 				if ( ! $wrap.hasClass('closed') ) {
   301 				if ( ! $wrap.hasClass('closed') ) {
   140 
   308 
   141 			stop: function( event, ui ) {
   309 			stop: function( event, ui ) {
   142 				var addNew, widgetNumber, $sidebar, $children, child, item,
   310 				var addNew, widgetNumber, $sidebar, $children, child, item,
   143 					$widget = ui.item,
   311 					$widget = ui.item,
   144 					id = the_id;
   312 					id = the_id;
       
   313 
       
   314 				// Reset the var to hold a previously closed sidebar.
       
   315 				wpWidgets.hoveredSidebar = null;
   145 
   316 
   146 				if ( $widget.hasClass('deleting') ) {
   317 				if ( $widget.hasClass('deleting') ) {
   147 					wpWidgets.save( $widget, 1, 0, 1 ); // delete widget
   318 					wpWidgets.save( $widget, 1, 0, 1 ); // delete widget
   148 					$widget.remove();
   319 					$widget.remove();
   149 					return;
   320 					return;
   172 						rem = 'div#' + id;
   343 						rem = 'div#' + id;
   173 					}
   344 					}
   174 
   345 
   175 					wpWidgets.save( $widget, 0, 0, 1 );
   346 					wpWidgets.save( $widget, 0, 0, 1 );
   176 					$widget.find('input.add_new').val('');
   347 					$widget.find('input.add_new').val('');
   177 					$( document ).trigger( 'widget-added', [ $widget ] );
   348 					$document.trigger( 'widget-added', [ $widget ] );
   178 				}
   349 				}
   179 
   350 
   180 				$sidebar = $widget.parent();
   351 				$sidebar = $widget.parent();
   181 
   352 
   182 				if ( $sidebar.parent().hasClass('closed') ) {
   353 				if ( $sidebar.parent().hasClass('closed') ) {
   183 					$sidebar.parent().removeClass('closed');
   354 					$sidebar.parent()
       
   355 						.removeClass( 'closed' )
       
   356 						.find( '.handlediv' ).attr( 'aria-expanded', 'true' );
       
   357 
   184 					$children = $sidebar.children('.widget');
   358 					$children = $sidebar.children('.widget');
   185 
   359 
   186 					// Make sure the dropped widget is at the top
   360 					// Make sure the dropped widget is at the top
   187 					if ( $children.length > 1 ) {
   361 					if ( $children.length > 1 ) {
   188 						child = $children.get(0);
   362 						child = $children.get(0);
   193 						}
   367 						}
   194 					}
   368 					}
   195 				}
   369 				}
   196 
   370 
   197 				if ( addNew ) {
   371 				if ( addNew ) {
   198 					$widget.find( 'a.widget-action' ).trigger('click');
   372 					$widget.find( '.widget-action' ).trigger( 'click' );
   199 				} else {
   373 				} else {
   200 					wpWidgets.saveOrder( $sidebar.attr('id') );
   374 					wpWidgets.saveOrder( $sidebar.attr('id') );
   201 				}
   375 				}
   202 			},
   376 			},
   203 
   377 
   239 				ui.draggable.addClass('deleting');
   413 				ui.draggable.addClass('deleting');
   240 				$('div.widget-placeholder').hide();
   414 				$('div.widget-placeholder').hide();
   241 
   415 
   242 				if ( ui.draggable.hasClass('ui-sortable-helper') ) {
   416 				if ( ui.draggable.hasClass('ui-sortable-helper') ) {
   243 					$('#removing-widget').show().children('span')
   417 					$('#removing-widget').show().children('span')
   244 					.html( ui.draggable.find('div.widget-title').children('h4').html() );
   418 					.html( ui.draggable.find( 'div.widget-title' ).children( 'h3' ).html() );
   245 				}
   419 				}
   246 			},
   420 			},
   247 			out: function(e,ui) {
   421 			out: function(e,ui) {
   248 				ui.draggable.removeClass('deleting');
   422 				ui.draggable.removeClass('deleting');
   249 				$('div.widget-placeholder').show();
   423 				$('div.widget-placeholder').show();
   252 		});
   426 		});
   253 
   427 
   254 		// Area Chooser
   428 		// Area Chooser
   255 		$( '#widgets-right .widgets-holder-wrap' ).each( function( index, element ) {
   429 		$( '#widgets-right .widgets-holder-wrap' ).each( function( index, element ) {
   256 			var $element = $( element ),
   430 			var $element = $( element ),
   257 				name = $element.find( '.sidebar-name h3' ).text(),
   431 				name = $element.find( '.sidebar-name h2' ).text(),
   258 				id = $element.find( '.widgets-sortables' ).attr( 'id' ),
   432 				id = $element.find( '.widgets-sortables' ).attr( 'id' ),
   259 				li = $('<li tabindex="0">').text( $.trim( name ) );
   433 				li = $('<li tabindex="0">').text( $.trim( name ) );
   260 
   434 
   261 			if ( index === 0 ) {
   435 			if ( index === 0 ) {
   262 				li.addClass( 'widgets-chooser-selected' );
   436 				li.addClass( 'widgets-chooser-selected' );
   293 			var $target = $( event.target );
   467 			var $target = $( event.target );
   294 
   468 
   295 			if ( $target.hasClass('button-primary') ) {
   469 			if ( $target.hasClass('button-primary') ) {
   296 				self.addWidget( chooser );
   470 				self.addWidget( chooser );
   297 				self.closeChooser();
   471 				self.closeChooser();
   298 			} else if ( $target.hasClass('button-secondary') ) {
   472 			} else if ( $target.hasClass( 'widgets-chooser-cancel' ) ) {
   299 				self.closeChooser();
   473 				self.closeChooser();
   300 			}
   474 			}
   301 		}).on( 'keyup.widgets-chooser', function( event ) {
   475 		}).on( 'keyup.widgets-chooser', function( event ) {
   302 			if ( event.which === $.ui.keyCode.ENTER ) {
   476 			if ( event.which === $.ui.keyCode.ENTER ) {
   303 				if ( $( event.target ).hasClass('button-secondary') ) {
   477 				if ( $( event.target ).hasClass( 'widgets-chooser-cancel' ) ) {
   304 					// Close instead of adding when pressing Enter on the Cancel button
   478 					// Close instead of adding when pressing Enter on the Cancel button
   305 					self.closeChooser();
   479 					self.closeChooser();
   306 				} else {
   480 				} else {
   307 					self.addWidget( chooser );
   481 					self.addWidget( chooser );
   308 					self.closeChooser();
   482 					self.closeChooser();
   329 				data['sidebars[' + $(this).attr('id') + ']'] = $(this).sortable('toArray').join(',');
   503 				data['sidebars[' + $(this).attr('id') + ']'] = $(this).sortable('toArray').join(',');
   330 			}
   504 			}
   331 		});
   505 		});
   332 
   506 
   333 		$.post( ajaxurl, data, function() {
   507 		$.post( ajaxurl, data, function() {
       
   508 			$( '#inactive-widgets-control-remove' ).prop( 'disabled' , ! $( '#wp_inactive_widgets .widget' ).length );
   334 			$( '.spinner' ).removeClass( 'is-active' );
   509 			$( '.spinner' ).removeClass( 'is-active' );
   335 		});
   510 		});
   336 	},
   511 	},
   337 
   512 
   338 	save : function( widget, del, animate, order ) {
   513 	save : function( widget, del, animate, order ) {
   339 		var sidebarId = widget.closest('div.widgets-sortables').attr('id'),
   514 		var self = this, data, a,
   340 			data = widget.find('form').serialize(), a;
   515 			sidebarId = widget.closest( 'div.widgets-sortables' ).attr( 'id' ),
       
   516 			form = widget.find( 'form' ),
       
   517 			isAdd = widget.find( 'input.add_new' ).val();
       
   518 
       
   519 		if ( ! del && ! isAdd && form.prop( 'checkValidity' ) && ! form[0].checkValidity() ) {
       
   520 			return;
       
   521 		}
       
   522 
       
   523 		data = form.serialize();
   341 
   524 
   342 		widget = $(widget);
   525 		widget = $(widget);
   343 		$( '.spinner', widget ).addClass( 'is-active' );
   526 		$( '.spinner', widget ).addClass( 'is-active' );
   344 
   527 
   345 		a = {
   528 		a = {
   353 		}
   536 		}
   354 
   537 
   355 		data += '&' + $.param(a);
   538 		data += '&' + $.param(a);
   356 
   539 
   357 		$.post( ajaxurl, data, function(r) {
   540 		$.post( ajaxurl, data, function(r) {
   358 			var id;
   541 			var id = $('input.widget-id', widget).val();
   359 
   542 
   360 			if ( del ) {
   543 			if ( del ) {
   361 				if ( ! $('input.widget_number', widget).val() ) {
   544 				if ( ! $('input.widget_number', widget).val() ) {
   362 					id = $('input.widget-id', widget).val();
       
   363 					$('#available-widgets').find('input.widget-id').each(function(){
   545 					$('#available-widgets').find('input.widget-id').each(function(){
   364 						if ( $(this).val() === id ) {
   546 						if ( $(this).val() === id ) {
   365 							$(this).closest('div.widget').show();
   547 							$(this).closest('div.widget').show();
   366 						}
   548 						}
   367 					});
   549 					});
   368 				}
   550 				}
   369 
   551 
   370 				if ( animate ) {
   552 				if ( animate ) {
   371 					order = 0;
   553 					order = 0;
   372 					widget.slideUp('fast', function(){
   554 					widget.slideUp( 'fast', function() {
   373 						$(this).remove();
   555 						$( this ).remove();
   374 						wpWidgets.saveOrder();
   556 						wpWidgets.saveOrder();
       
   557 						delete self.dirtyWidgets[ id ];
   375 					});
   558 					});
   376 				} else {
   559 				} else {
   377 					widget.remove();
   560 					widget.remove();
       
   561 					delete self.dirtyWidgets[ id ];
       
   562 
       
   563 					if ( sidebarId === 'wp_inactive_widgets' ) {
       
   564 						$( '#inactive-widgets-control-remove' ).prop( 'disabled' , ! $( '#wp_inactive_widgets .widget' ).length );
       
   565 					}
   378 				}
   566 				}
   379 			} else {
   567 			} else {
   380 				$( '.spinner' ).removeClass( 'is-active' );
   568 				$( '.spinner' ).removeClass( 'is-active' );
   381 				if ( r && r.length > 2 ) {
   569 				if ( r && r.length > 2 ) {
   382 					$( 'div.widget-content', widget ).html( r );
   570 					$( 'div.widget-content', widget ).html( r );
   383 					wpWidgets.appendTitle( widget );
   571 					wpWidgets.appendTitle( widget );
   384 					$( document ).trigger( 'widget-updated', [ widget ] );
   572 
   385 				}
   573 					// Re-disable the save button.
   386 			}
   574 					widget.find( '.widget-control-save' ).prop( 'disabled', true ).val( wpWidgets.l10n.saved );
       
   575 
       
   576 					widget.removeClass( 'widget-dirty' );
       
   577 
       
   578 					// Clear the dirty flag from the widget.
       
   579 					delete self.dirtyWidgets[ id ];
       
   580 
       
   581 					$document.trigger( 'widget-updated', [ widget ] );
       
   582 
       
   583 					if ( sidebarId === 'wp_inactive_widgets' ) {
       
   584 						$( '#inactive-widgets-control-remove' ).prop( 'disabled' , ! $( '#wp_inactive_widgets .widget' ).length );
       
   585 					}
       
   586 				}
       
   587 			}
       
   588 
   387 			if ( order ) {
   589 			if ( order ) {
   388 				wpWidgets.saveOrder();
   590 				wpWidgets.saveOrder();
   389 			}
   591 			}
   390 		});
   592 		});
       
   593 	},
       
   594 
       
   595 	removeInactiveWidgets : function() {
       
   596 		var $element = $( '.remove-inactive-widgets' ), self = this, a, data;
       
   597 
       
   598 		$( '.spinner', $element ).addClass( 'is-active' );
       
   599 
       
   600 		a = {
       
   601 			action : 'delete-inactive-widgets',
       
   602 			removeinactivewidgets : $( '#_wpnonce_remove_inactive_widgets' ).val()
       
   603 		};
       
   604 
       
   605 		data = $.param( a );
       
   606 
       
   607 		$.post( ajaxurl, data, function() {
       
   608 			$( '#wp_inactive_widgets .widget' ).each(function() {
       
   609 				var $widget = $( this );
       
   610 				delete self.dirtyWidgets[ $widget.find( 'input.widget-id' ).val() ];
       
   611 				$widget.remove();
       
   612 			});
       
   613 			$( '#inactive-widgets-control-remove' ).prop( 'disabled', true );
       
   614 			$( '.spinner', $element ).removeClass( 'is-active' );
       
   615 		} );
   391 	},
   616 	},
   392 
   617 
   393 	appendTitle : function(widget) {
   618 	appendTitle : function(widget) {
   394 		var title = $('input[id*="-title"]', widget).val() || '';
   619 		var title = $('input[id*="-title"]', widget).val() || '';
   395 
   620 
   402 
   627 
   403 	},
   628 	},
   404 
   629 
   405 	close : function(widget) {
   630 	close : function(widget) {
   406 		widget.children('.widget-inside').slideUp('fast', function() {
   631 		widget.children('.widget-inside').slideUp('fast', function() {
   407 			widget.attr( 'style', '' );
   632 			widget.attr( 'style', '' )
       
   633 				.find( '.widget-top button.widget-action' )
       
   634 					.attr( 'aria-expanded', 'false' )
       
   635 					.focus();
   408 		});
   636 		});
   409 	},
   637 	},
   410 
   638 
   411 	addWidget: function( chooser ) {
   639 	addWidget: function( chooser ) {
   412 		var widget, widgetId, add, n, viewportTop, viewportBottom, sidebarBounds,
   640 		var widget, widgetId, add, n, viewportTop, viewportBottom, sidebarBounds,
   434 		} else if ( 'single' === add ) {
   662 		} else if ( 'single' === add ) {
   435 			widget.attr( 'id', 'new-' + widgetId );
   663 			widget.attr( 'id', 'new-' + widgetId );
   436 			$( '#' + widgetId ).hide();
   664 			$( '#' + widgetId ).hide();
   437 		}
   665 		}
   438 
   666 
   439 		// Open the widgets container
   667 		// Open the widgets container.
   440 		sidebar.closest( '.widgets-holder-wrap' ).removeClass('closed');
   668 		sidebar.closest( '.widgets-holder-wrap' )
       
   669 			.removeClass( 'closed' )
       
   670 			.find( '.handlediv' ).attr( 'aria-expanded', 'true' );
   441 
   671 
   442 		sidebar.append( widget );
   672 		sidebar.append( widget );
   443 		sidebar.sortable('refresh');
   673 		sidebar.sortable('refresh');
   444 
   674 
   445 		wpWidgets.save( widget, 0, 0, 1 );
   675 		wpWidgets.save( widget, 0, 0, 1 );
   446 		// No longer "new" widget
   676 		// No longer "new" widget
   447 		widget.find( 'input.add_new' ).val('');
   677 		widget.find( 'input.add_new' ).val('');
   448 
   678 
   449 		$( document ).trigger( 'widget-added', [ widget ] );
   679 		$document.trigger( 'widget-added', [ widget ] );
   450 
   680 
   451 		/*
   681 		/*
   452 		 * Check if any part of the sidebar is visible in the viewport. If it is, don't scroll.
   682 		 * Check if any part of the sidebar is visible in the viewport. If it is, don't scroll.
   453 		 * Otherwise, scroll up to so the sidebar is in view.
   683 		 * Otherwise, scroll up to so the sidebar is in view.
   454 		 *
   684 		 *
   484 	},
   714 	},
   485 
   715 
   486 	clearWidgetSelection: function() {
   716 	clearWidgetSelection: function() {
   487 		$( '#widgets-left' ).removeClass( 'chooser' );
   717 		$( '#widgets-left' ).removeClass( 'chooser' );
   488 		$( '.widget-in-question' ).removeClass( 'widget-in-question' );
   718 		$( '.widget-in-question' ).removeClass( 'widget-in-question' );
       
   719 	},
       
   720 
       
   721 	/**
       
   722 	 * Closes a Sidebar that was previously closed, but opened by dragging a Widget over it.
       
   723 	 *
       
   724 	 * Used when a Widget gets dragged in/out of the Sidebar and never dropped.
       
   725 	 *
       
   726 	 * @param {object} event jQuery event object.
       
   727 	 */
       
   728 	closeSidebar: function( event ) {
       
   729 		this.hoveredSidebar
       
   730 			.addClass( 'closed' )
       
   731 			.find( '.handlediv' ).attr( 'aria-expanded', 'false' );
       
   732 
       
   733 		$( event.target ).css( 'min-height', '' );
       
   734 		this.hoveredSidebar = null;
   489 	}
   735 	}
   490 };
   736 };
   491 
   737 
   492 $(document).ready( function(){ wpWidgets.init(); } );
   738 $document.ready( function(){ wpWidgets.init(); } );
   493 
   739 
   494 })(jQuery);
   740 })(jQuery);