angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

postbox.js (18841B)


      1 /**
      2  * Contains the postboxes logic, opening and closing postboxes, reordering and saving
      3  * the state and ordering to the database.
      4  *
      5  * @since 2.5.0
      6  * @requires jQuery
      7  * @output wp-admin/js/postbox.js
      8  */
      9 
     10 /* global ajaxurl, postboxes */
     11 
     12 (function($) {
     13 	var $document = $( document ),
     14 		__ = wp.i18n.__;
     15 
     16 	/**
     17 	 * This object contains all function to handle the behaviour of the post boxes. The post boxes are the boxes you see
     18 	 * around the content on the edit page.
     19 	 *
     20 	 * @since 2.7.0
     21 	 *
     22 	 * @namespace postboxes
     23 	 *
     24 	 * @type {Object}
     25 	 */
     26 	window.postboxes = {
     27 
     28 		/**
     29 		 * Handles a click on either the postbox heading or the postbox open/close icon.
     30 		 *
     31 		 * Opens or closes the postbox. Expects `this` to equal the clicked element.
     32 		 * Calls postboxes.pbshow if the postbox has been opened, calls postboxes.pbhide
     33 		 * if the postbox has been closed.
     34 		 *
     35 		 * @since 4.4.0
     36 		 *
     37 		 * @memberof postboxes
     38 		 *
     39 		 * @fires postboxes#postbox-toggled
     40 		 *
     41 		 * @return {void}
     42 		 */
     43 		handle_click : function () {
     44 			var $el = $( this ),
     45 				p = $el.closest( '.postbox' ),
     46 				id = p.attr( 'id' ),
     47 				ariaExpandedValue;
     48 
     49 			if ( 'dashboard_browser_nag' === id ) {
     50 				return;
     51 			}
     52 
     53 			p.toggleClass( 'closed' );
     54 			ariaExpandedValue = ! p.hasClass( 'closed' );
     55 
     56 			if ( $el.hasClass( 'handlediv' ) ) {
     57 				// The handle button was clicked.
     58 				$el.attr( 'aria-expanded', ariaExpandedValue );
     59 			} else {
     60 				// The handle heading was clicked.
     61 				$el.closest( '.postbox' ).find( 'button.handlediv' )
     62 					.attr( 'aria-expanded', ariaExpandedValue );
     63 			}
     64 
     65 			if ( postboxes.page !== 'press-this' ) {
     66 				postboxes.save_state( postboxes.page );
     67 			}
     68 
     69 			if ( id ) {
     70 				if ( !p.hasClass('closed') && typeof postboxes.pbshow === 'function' ) {
     71 					postboxes.pbshow( id );
     72 				} else if ( p.hasClass('closed') && typeof postboxes.pbhide === 'function' ) {
     73 					postboxes.pbhide( id );
     74 				}
     75 			}
     76 
     77 			/**
     78 			 * Fires when a postbox has been opened or closed.
     79 			 *
     80 			 * Contains a jQuery object with the relevant postbox element.
     81 			 *
     82 			 * @since 4.0.0
     83 			 * @ignore
     84 			 *
     85 			 * @event postboxes#postbox-toggled
     86 			 * @type {Object}
     87 			 */
     88 			$document.trigger( 'postbox-toggled', p );
     89 		},
     90 
     91 		/**
     92 		 * Handles clicks on the move up/down buttons.
     93 		 *
     94 		 * @since 5.5.0
     95 		 *
     96 		 * @return {void}
     97 		 */
     98 		handleOrder: function() {
     99 			var button = $( this ),
    100 				postbox = button.closest( '.postbox' ),
    101 				postboxId = postbox.attr( 'id' ),
    102 				postboxesWithinSortables = postbox.closest( '.meta-box-sortables' ).find( '.postbox:visible' ),
    103 				postboxesWithinSortablesCount = postboxesWithinSortables.length,
    104 				postboxWithinSortablesIndex = postboxesWithinSortables.index( postbox ),
    105 				firstOrLastPositionMessage;
    106 
    107 			if ( 'dashboard_browser_nag' === postboxId ) {
    108 				return;
    109 			}
    110 
    111 			// If on the first or last position, do nothing and send an audible message to screen reader users.
    112 			if ( 'true' === button.attr( 'aria-disabled' ) ) {
    113 				firstOrLastPositionMessage = button.hasClass( 'handle-order-higher' ) ?
    114 					__( 'The box is on the first position' ) :
    115 					__( 'The box is on the last position' );
    116 
    117 				wp.a11y.speak( firstOrLastPositionMessage );
    118 				return;
    119 			}
    120 
    121 			// Move a postbox up.
    122 			if ( button.hasClass( 'handle-order-higher' ) ) {
    123 				// If the box is first within a sortable area, move it to the previous sortable area.
    124 				if ( 0 === postboxWithinSortablesIndex ) {
    125 					postboxes.handleOrderBetweenSortables( 'previous', button, postbox );
    126 					return;
    127 				}
    128 
    129 				postbox.prevAll( '.postbox:visible' ).eq( 0 ).before( postbox );
    130 				button.trigger( 'focus' );
    131 				postboxes.updateOrderButtonsProperties();
    132 				postboxes.save_order( postboxes.page );
    133 			}
    134 
    135 			// Move a postbox down.
    136 			if ( button.hasClass( 'handle-order-lower' ) ) {
    137 				// If the box is last within a sortable area, move it to the next sortable area.
    138 				if ( postboxWithinSortablesIndex + 1 === postboxesWithinSortablesCount ) {
    139 					postboxes.handleOrderBetweenSortables( 'next', button, postbox );
    140 					return;
    141 				}
    142 
    143 				postbox.nextAll( '.postbox:visible' ).eq( 0 ).after( postbox );
    144 				button.trigger( 'focus' );
    145 				postboxes.updateOrderButtonsProperties();
    146 				postboxes.save_order( postboxes.page );
    147 			}
    148 
    149 		},
    150 
    151 		/**
    152 		 * Moves postboxes between the sortables areas.
    153 		 *
    154 		 * @since 5.5.0
    155 		 *
    156 		 * @param {string} position The "previous" or "next" sortables area.
    157 		 * @param {Object} button   The jQuery object representing the button that was clicked.
    158 		 * @param {Object} postbox  The jQuery object representing the postbox to be moved.
    159 		 *
    160 		 * @return {void}
    161 		 */
    162 		handleOrderBetweenSortables: function( position, button, postbox ) {
    163 			var closestSortablesId = button.closest( '.meta-box-sortables' ).attr( 'id' ),
    164 				sortablesIds = [],
    165 				sortablesIndex,
    166 				detachedPostbox;
    167 
    168 			// Get the list of sortables within the page.
    169 			$( '.meta-box-sortables:visible' ).each( function() {
    170 				sortablesIds.push( $( this ).attr( 'id' ) );
    171 			});
    172 
    173 			// Return if there's only one visible sortables area, e.g. in the block editor page.
    174 			if ( 1 === sortablesIds.length ) {
    175 				return;
    176 			}
    177 
    178 			// Find the index of the current sortables area within all the sortable areas.
    179 			sortablesIndex = $.inArray( closestSortablesId, sortablesIds );
    180 			// Detach the postbox to be moved.
    181 			detachedPostbox = postbox.detach();
    182 
    183 			// Move the detached postbox to its new position.
    184 			if ( 'previous' === position ) {
    185 				$( detachedPostbox ).appendTo( '#' + sortablesIds[ sortablesIndex - 1 ] );
    186 			}
    187 
    188 			if ( 'next' === position ) {
    189 				$( detachedPostbox ).prependTo( '#' + sortablesIds[ sortablesIndex + 1 ] );
    190 			}
    191 
    192 			postboxes._mark_area();
    193 			button.focus();
    194 			postboxes.updateOrderButtonsProperties();
    195 			postboxes.save_order( postboxes.page );
    196 		},
    197 
    198 		/**
    199 		 * Update the move buttons properties depending on the postbox position.
    200 		 *
    201 		 * @since 5.5.0
    202 		 *
    203 		 * @return {void}
    204 		 */
    205 		updateOrderButtonsProperties: function() {
    206 			var firstSortablesId = $( '.meta-box-sortables:visible:first' ).attr( 'id' ),
    207 				lastSortablesId = $( '.meta-box-sortables:visible:last' ).attr( 'id' ),
    208 				firstPostbox = $( '.postbox:visible:first' ),
    209 				lastPostbox = $( '.postbox:visible:last' ),
    210 				firstPostboxId = firstPostbox.attr( 'id' ),
    211 				lastPostboxId = lastPostbox.attr( 'id' ),
    212 				firstPostboxSortablesId = firstPostbox.closest( '.meta-box-sortables' ).attr( 'id' ),
    213 				lastPostboxSortablesId = lastPostbox.closest( '.meta-box-sortables' ).attr( 'id' ),
    214 				moveUpButtons = $( '.handle-order-higher' ),
    215 				moveDownButtons = $( '.handle-order-lower' );
    216 
    217 			// Enable all buttons as a reset first.
    218 			moveUpButtons
    219 				.attr( 'aria-disabled', 'false' )
    220 				.removeClass( 'hidden' );
    221 			moveDownButtons
    222 				.attr( 'aria-disabled', 'false' )
    223 				.removeClass( 'hidden' );
    224 
    225 			// When there's only one "sortables" area (e.g. in the block editor) and only one visible postbox, hide the buttons.
    226 			if ( firstSortablesId === lastSortablesId && firstPostboxId === lastPostboxId ) {
    227 				moveUpButtons.addClass( 'hidden' );
    228 				moveDownButtons.addClass( 'hidden' );
    229 			}
    230 
    231 			// Set an aria-disabled=true attribute on the first visible "move" buttons.
    232 			if ( firstSortablesId === firstPostboxSortablesId ) {
    233 				$( firstPostbox ).find( '.handle-order-higher' ).attr( 'aria-disabled', 'true' );
    234 			}
    235 
    236 			// Set an aria-disabled=true attribute on the last visible "move" buttons.
    237 			if ( lastSortablesId === lastPostboxSortablesId ) {
    238 				$( '.postbox:visible .handle-order-lower' ).last().attr( 'aria-disabled', 'true' );
    239 			}
    240 		},
    241 
    242 		/**
    243 		 * Adds event handlers to all postboxes and screen option on the current page.
    244 		 *
    245 		 * @since 2.7.0
    246 		 *
    247 		 * @memberof postboxes
    248 		 *
    249 		 * @param {string} page The page we are currently on.
    250 		 * @param {Object} [args]
    251 		 * @param {Function} args.pbshow A callback that is called when a postbox opens.
    252 		 * @param {Function} args.pbhide A callback that is called when a postbox closes.
    253 		 * @return {void}
    254 		 */
    255 		add_postbox_toggles : function (page, args) {
    256 			var $handles = $( '.postbox .hndle, .postbox .handlediv' ),
    257 				$orderButtons = $( '.postbox .handle-order-higher, .postbox .handle-order-lower' );
    258 
    259 			this.page = page;
    260 			this.init( page, args );
    261 
    262 			$handles.on( 'click.postboxes', this.handle_click );
    263 
    264 			// Handle the order of the postboxes.
    265 			$orderButtons.on( 'click.postboxes', this.handleOrder );
    266 
    267 			/**
    268 			 * @since 2.7.0
    269 			 */
    270 			$('.postbox .hndle a').on( 'click', function(e) {
    271 				e.stopPropagation();
    272 			});
    273 
    274 			/**
    275 			 * Hides a postbox.
    276 			 *
    277 			 * Event handler for the postbox dismiss button. After clicking the button
    278 			 * the postbox will be hidden.
    279 			 *
    280 			 * As of WordPress 5.5, this is only used for the browser update nag.
    281 			 *
    282 			 * @since 3.2.0
    283 			 *
    284 			 * @return {void}
    285 			 */
    286 			$( '.postbox a.dismiss' ).on( 'click.postboxes', function( e ) {
    287 				var hide_id = $(this).parents('.postbox').attr('id') + '-hide';
    288 				e.preventDefault();
    289 				$( '#' + hide_id ).prop('checked', false).triggerHandler('click');
    290 			});
    291 
    292 			/**
    293 			 * Hides the postbox element
    294 			 *
    295 			 * Event handler for the screen options checkboxes. When a checkbox is
    296 			 * clicked this function will hide or show the relevant postboxes.
    297 			 *
    298 			 * @since 2.7.0
    299 			 * @ignore
    300 			 *
    301 			 * @fires postboxes#postbox-toggled
    302 			 *
    303 			 * @return {void}
    304 			 */
    305 			$('.hide-postbox-tog').on('click.postboxes', function() {
    306 				var $el = $(this),
    307 					boxId = $el.val(),
    308 					$postbox = $( '#' + boxId );
    309 
    310 				if ( $el.prop( 'checked' ) ) {
    311 					$postbox.show();
    312 					if ( typeof postboxes.pbshow === 'function' ) {
    313 						postboxes.pbshow( boxId );
    314 					}
    315 				} else {
    316 					$postbox.hide();
    317 					if ( typeof postboxes.pbhide === 'function' ) {
    318 						postboxes.pbhide( boxId );
    319 					}
    320 				}
    321 
    322 				postboxes.save_state( page );
    323 				postboxes._mark_area();
    324 
    325 				/**
    326 				 * @since 4.0.0
    327 				 * @see postboxes.handle_click
    328 				 */
    329 				$document.trigger( 'postbox-toggled', $postbox );
    330 			});
    331 
    332 			/**
    333 			 * Changes the amount of columns based on the layout preferences.
    334 			 *
    335 			 * @since 2.8.0
    336 			 *
    337 			 * @return {void}
    338 			 */
    339 			$('.columns-prefs input[type="radio"]').on('click.postboxes', function(){
    340 				var n = parseInt($(this).val(), 10);
    341 
    342 				if ( n ) {
    343 					postboxes._pb_edit(n);
    344 					postboxes.save_order( page );
    345 				}
    346 			});
    347 		},
    348 
    349 		/**
    350 		 * Initializes all the postboxes, mainly their sortable behaviour.
    351 		 *
    352 		 * @since 2.7.0
    353 		 *
    354 		 * @memberof postboxes
    355 		 *
    356 		 * @param {string} page The page we are currently on.
    357 		 * @param {Object} [args={}] The arguments for the postbox initializer.
    358 		 * @param {Function} args.pbshow A callback that is called when a postbox opens.
    359 		 * @param {Function} args.pbhide A callback that is called when a postbox
    360 		 *                               closes.
    361 		 *
    362 		 * @return {void}
    363 		 */
    364 		init : function(page, args) {
    365 			var isMobile = $( document.body ).hasClass( 'mobile' ),
    366 				$handleButtons = $( '.postbox .handlediv' );
    367 
    368 			$.extend( this, args || {} );
    369 			$('.meta-box-sortables').sortable({
    370 				placeholder: 'sortable-placeholder',
    371 				connectWith: '.meta-box-sortables',
    372 				items: '.postbox',
    373 				handle: '.hndle',
    374 				cursor: 'move',
    375 				delay: ( isMobile ? 200 : 0 ),
    376 				distance: 2,
    377 				tolerance: 'pointer',
    378 				forcePlaceholderSize: true,
    379 				helper: function( event, element ) {
    380 					/* `helper: 'clone'` is equivalent to `return element.clone();`
    381 					 * Cloning a checked radio and then inserting that clone next to the original
    382 					 * radio unchecks the original radio (since only one of the two can be checked).
    383 					 * We get around this by renaming the helper's inputs' name attributes so that,
    384 					 * when the helper is inserted into the DOM for the sortable, no radios are
    385 					 * duplicated, and no original radio gets unchecked.
    386 					 */
    387 					return element.clone()
    388 						.find( ':input' )
    389 							.attr( 'name', function( i, currentName ) {
    390 								return 'sort_' + parseInt( Math.random() * 100000, 10 ).toString() + '_' + currentName;
    391 							} )
    392 						.end();
    393 				},
    394 				opacity: 0.65,
    395 				start: function() {
    396 					$( 'body' ).addClass( 'is-dragging-metaboxes' );
    397 					// Refresh the cached positions of all the sortable items so that the min-height set while dragging works.
    398 					$( '.meta-box-sortables' ).sortable( 'refreshPositions' );
    399 				},
    400 				stop: function() {
    401 					var $el = $( this );
    402 
    403 					$( 'body' ).removeClass( 'is-dragging-metaboxes' );
    404 
    405 					if ( $el.find( '#dashboard_browser_nag' ).is( ':visible' ) && 'dashboard_browser_nag' != this.firstChild.id ) {
    406 						$el.sortable('cancel');
    407 						return;
    408 					}
    409 
    410 					postboxes.updateOrderButtonsProperties();
    411 					postboxes.save_order(page);
    412 				},
    413 				receive: function(e,ui) {
    414 					if ( 'dashboard_browser_nag' == ui.item[0].id )
    415 						$(ui.sender).sortable('cancel');
    416 
    417 					postboxes._mark_area();
    418 					$document.trigger( 'postbox-moved', ui.item );
    419 				}
    420 			});
    421 
    422 			if ( isMobile ) {
    423 				$(document.body).on('orientationchange.postboxes', function(){ postboxes._pb_change(); });
    424 				this._pb_change();
    425 			}
    426 
    427 			this._mark_area();
    428 
    429 			// Update the "move" buttons properties.
    430 			this.updateOrderButtonsProperties();
    431 			$document.on( 'postbox-toggled', this.updateOrderButtonsProperties );
    432 
    433 			// Set the handle buttons `aria-expanded` attribute initial value on page load.
    434 			$handleButtons.each( function () {
    435 				var $el = $( this );
    436 				$el.attr( 'aria-expanded', ! $el.closest( '.postbox' ).hasClass( 'closed' ) );
    437 			});
    438 		},
    439 
    440 		/**
    441 		 * Saves the state of the postboxes to the server.
    442 		 *
    443 		 * It sends two lists, one with all the closed postboxes, one with all the
    444 		 * hidden postboxes.
    445 		 *
    446 		 * @since 2.7.0
    447 		 *
    448 		 * @memberof postboxes
    449 		 *
    450 		 * @param {string} page The page we are currently on.
    451 		 * @return {void}
    452 		 */
    453 		save_state : function(page) {
    454 			var closed, hidden;
    455 
    456 			// Return on the nav-menus.php screen, see #35112.
    457 			if ( 'nav-menus' === page ) {
    458 				return;
    459 			}
    460 
    461 			closed = $( '.postbox' ).filter( '.closed' ).map( function() { return this.id; } ).get().join( ',' );
    462 			hidden = $( '.postbox' ).filter( ':hidden' ).map( function() { return this.id; } ).get().join( ',' );
    463 
    464 			$.post(ajaxurl, {
    465 				action: 'closed-postboxes',
    466 				closed: closed,
    467 				hidden: hidden,
    468 				closedpostboxesnonce: jQuery('#closedpostboxesnonce').val(),
    469 				page: page
    470 			});
    471 		},
    472 
    473 		/**
    474 		 * Saves the order of the postboxes to the server.
    475 		 *
    476 		 * Sends a list of all postboxes inside a sortable area to the server.
    477 		 *
    478 		 * @since 2.8.0
    479 		 *
    480 		 * @memberof postboxes
    481 		 *
    482 		 * @param {string} page The page we are currently on.
    483 		 * @return {void}
    484 		 */
    485 		save_order : function(page) {
    486 			var postVars, page_columns = $('.columns-prefs input:checked').val() || 0;
    487 
    488 			postVars = {
    489 				action: 'meta-box-order',
    490 				_ajax_nonce: $('#meta-box-order-nonce').val(),
    491 				page_columns: page_columns,
    492 				page: page
    493 			};
    494 
    495 			$('.meta-box-sortables').each( function() {
    496 				postVars[ 'order[' + this.id.split( '-' )[0] + ']' ] = $( this ).sortable( 'toArray' ).join( ',' );
    497 			} );
    498 
    499 			$.post(
    500 				ajaxurl,
    501 				postVars,
    502 				function( response ) {
    503 					if ( response.success ) {
    504 						wp.a11y.speak( __( 'The boxes order has been saved.' ) );
    505 					}
    506 				}
    507 			);
    508 		},
    509 
    510 		/**
    511 		 * Marks empty postbox areas.
    512 		 *
    513 		 * Adds a message to empty sortable areas on the dashboard page. Also adds a
    514 		 * border around the side area on the post edit screen if there are no postboxes
    515 		 * present.
    516 		 *
    517 		 * @since 3.3.0
    518 		 * @access private
    519 		 *
    520 		 * @memberof postboxes
    521 		 *
    522 		 * @return {void}
    523 		 */
    524 		_mark_area : function() {
    525 			var visible = $( 'div.postbox:visible' ).length,
    526 				visibleSortables = $( '#dashboard-widgets .meta-box-sortables:visible, #post-body .meta-box-sortables:visible' ),
    527 				areAllVisibleSortablesEmpty = true;
    528 
    529 			visibleSortables.each( function() {
    530 				var t = $(this);
    531 
    532 				if ( visible == 1 || t.children( '.postbox:visible' ).length ) {
    533 					t.removeClass('empty-container');
    534 					areAllVisibleSortablesEmpty = false;
    535 				}
    536 				else {
    537 					t.addClass('empty-container');
    538 				}
    539 			});
    540 
    541 			postboxes.updateEmptySortablesText( visibleSortables, areAllVisibleSortablesEmpty );
    542 		},
    543 
    544 		/**
    545 		 * Updates the text for the empty sortable areas on the Dashboard.
    546 		 *
    547 		 * @since 5.5.0
    548 		 *
    549 		 * @param {Object}  visibleSortables            The jQuery object representing the visible sortable areas.
    550 		 * @param {boolean} areAllVisibleSortablesEmpty Whether all the visible sortable areas are "empty".
    551 		 *
    552 		 * @return {void}
    553 		 */
    554 		updateEmptySortablesText: function( visibleSortables, areAllVisibleSortablesEmpty ) {
    555 			var isDashboard = $( '#dashboard-widgets' ).length,
    556 				emptySortableText = areAllVisibleSortablesEmpty ?  __( 'Add boxes from the Screen Options menu' ) : __( 'Drag boxes here' );
    557 
    558 			if ( ! isDashboard ) {
    559 				return;
    560 			}
    561 
    562 			visibleSortables.each( function() {
    563 				if ( $( this ).hasClass( 'empty-container' ) ) {
    564 					$( this ).attr( 'data-emptyString', emptySortableText );
    565 				}
    566 			} );
    567 		},
    568 
    569 		/**
    570 		 * Changes the amount of columns on the post edit page.
    571 		 *
    572 		 * @since 3.3.0
    573 		 * @access private
    574 		 *
    575 		 * @memberof postboxes
    576 		 *
    577 		 * @fires postboxes#postboxes-columnchange
    578 		 *
    579 		 * @param {number} n The amount of columns to divide the post edit page in.
    580 		 * @return {void}
    581 		 */
    582 		_pb_edit : function(n) {
    583 			var el = $('.metabox-holder').get(0);
    584 
    585 			if ( el ) {
    586 				el.className = el.className.replace(/columns-\d+/, 'columns-' + n);
    587 			}
    588 
    589 			/**
    590 			 * Fires when the amount of columns on the post edit page has been changed.
    591 			 *
    592 			 * @since 4.0.0
    593 			 * @ignore
    594 			 *
    595 			 * @event postboxes#postboxes-columnchange
    596 			 */
    597 			$( document ).trigger( 'postboxes-columnchange' );
    598 		},
    599 
    600 		/**
    601 		 * Changes the amount of columns the postboxes are in based on the current
    602 		 * orientation of the browser.
    603 		 *
    604 		 * @since 3.3.0
    605 		 * @access private
    606 		 *
    607 		 * @memberof postboxes
    608 		 *
    609 		 * @return {void}
    610 		 */
    611 		_pb_change : function() {
    612 			var check = $( 'label.columns-prefs-1 input[type="radio"]' );
    613 
    614 			switch ( window.orientation ) {
    615 				case 90:
    616 				case -90:
    617 					if ( !check.length || !check.is(':checked') )
    618 						this._pb_edit(2);
    619 					break;
    620 				case 0:
    621 				case 180:
    622 					if ( $( '#poststuff' ).length ) {
    623 						this._pb_edit(1);
    624 					} else {
    625 						if ( !check.length || !check.is(':checked') )
    626 							this._pb_edit(2);
    627 					}
    628 					break;
    629 			}
    630 		},
    631 
    632 		/* Callbacks */
    633 
    634 		/**
    635 		 * @since 2.7.0
    636 		 * @access public
    637 		 *
    638 		 * @property {Function|boolean} pbshow A callback that is called when a postbox
    639 		 *                                     is opened.
    640 		 * @memberof postboxes
    641 		 */
    642 		pbshow : false,
    643 
    644 		/**
    645 		 * @since 2.7.0
    646 		 * @access public
    647 		 * @property {Function|boolean} pbhide A callback that is called when a postbox
    648 		 *                                     is closed.
    649 		 * @memberof postboxes
    650 		 */
    651 		pbhide : false
    652 	};
    653 
    654 }(jQuery));