wp/wp-admin/js/postbox.js
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 /* global ajaxurl */
     1 /**
     2 
     2  * Contains the postboxes logic, opening and closing postboxes, reordering and saving
       
     3  * the state and ordering to the database.
       
     4  *
       
     5  * @summary Contains postboxes logic
       
     6  *
       
     7  * @since 2.5.0
       
     8  * @requires jQuery
       
     9  */
       
    10 
       
    11 /* global ajaxurl, postBoxL10n */
       
    12 
       
    13 /**
       
    14  * This object contains all function to handle the behaviour of the post boxes. The post boxes are the boxes you see
       
    15  * around the content on the edit page.
       
    16  *
       
    17  * @since 2.7.0
       
    18  *
       
    19  * @namespace postboxes
       
    20  *
       
    21  * @type {Object}
       
    22  */
     3 var postboxes;
    23 var postboxes;
     4 
    24 
     5 (function($) {
    25 (function($) {
     6 	var $document = $( document );
    26 	var $document = $( document );
     7 
    27 
     8 	postboxes = {
    28 	postboxes = {
     9 		add_postbox_toggles : function(page, args) {
    29 
    10 			var self = this;
    30 		/**
    11 
    31 		 * @summary Handles a click on either the postbox heading or the postbox open/close icon.
    12 			self.init(page, args);
    32 		 *
    13 
    33 		 * Opens or closes the postbox. Expects `this` to equal the clicked element.
    14 			$('.postbox .hndle, .postbox .handlediv').bind('click.postboxes', function() {
    34 		 * Calls postboxes.pbshow if the postbox has been opened, calls postboxes.pbhide
    15 				var p = $(this).parent('.postbox'), id = p.attr('id');
    35 		 * if the postbox has been closed.
    16 
    36 		 *
    17 				if ( 'dashboard_browser_nag' == id )
    37 		 * @since 4.4.0
    18 					return;
    38 		 * @memberof postboxes
    19 
    39 		 * @fires postboxes#postbox-toggled
    20 				p.toggleClass('closed');
    40 		 *
    21 
    41 		 * @returns {void}
    22 				if ( page != 'press-this' )
    42 		 */
    23 					self.save_state(page);
    43 		handle_click : function () {
    24 
    44 			var $el = $( this ),
    25 				if ( id ) {
    45 				p = $el.parent( '.postbox' ),
    26 					if ( !p.hasClass('closed') && $.isFunction(postboxes.pbshow) )
    46 				id = p.attr( 'id' ),
    27 						self.pbshow(id);
    47 				ariaExpandedValue;
    28 					else if ( p.hasClass('closed') && $.isFunction(postboxes.pbhide) )
    48 
    29 						self.pbhide(id);
    49 			if ( 'dashboard_browser_nag' === id ) {
    30 				}
    50 				return;
    31 
    51 			}
    32 				$document.trigger( 'postbox-toggled', p );
    52 
    33 			});
    53 			p.toggleClass( 'closed' );
    34 
    54 
       
    55 			ariaExpandedValue = ! p.hasClass( 'closed' );
       
    56 
       
    57 			if ( $el.hasClass( 'handlediv' ) ) {
       
    58 				// The handle button was clicked.
       
    59 				$el.attr( 'aria-expanded', ariaExpandedValue );
       
    60 			} else {
       
    61 				// The handle heading was clicked.
       
    62 				$el.closest( '.postbox' ).find( 'button.handlediv' )
       
    63 					.attr( 'aria-expanded', ariaExpandedValue );
       
    64 			}
       
    65 
       
    66 			if ( postboxes.page !== 'press-this' ) {
       
    67 				postboxes.save_state( postboxes.page );
       
    68 			}
       
    69 
       
    70 			if ( id ) {
       
    71 				if ( !p.hasClass('closed') && $.isFunction( postboxes.pbshow ) ) {
       
    72 					postboxes.pbshow( id );
       
    73 				} else if ( p.hasClass('closed') && $.isFunction( postboxes.pbhide ) ) {
       
    74 					postboxes.pbhide( id );
       
    75 				}
       
    76 			}
       
    77 
       
    78 			/**
       
    79 			 * @summary Fires when a postbox has been opened or closed.
       
    80 			 *
       
    81 			 * Contains a jQuery object with the relevant postbox element.
       
    82 			 *
       
    83 			 * @since 4.0.0
       
    84 			 * @event postboxes#postbox-toggled
       
    85 			 * @type {Object}
       
    86 			 */
       
    87 			$document.trigger( 'postbox-toggled', p );
       
    88 		},
       
    89 
       
    90 		/**
       
    91 		 * Adds event handlers to all postboxes and screen option on the current page.
       
    92 		 *
       
    93 		 * @since 2.7.0
       
    94 		 * @memberof postboxes
       
    95 		 *
       
    96 		 * @param {string} page The page we are currently on.
       
    97 		 * @param {Object} [args]
       
    98 		 * @param {Function} args.pbshow A callback that is called when a postbox opens.
       
    99 		 * @param {Function} args.pbhide A callback that is called when a postbox closes.
       
   100 		 * @returns {void}
       
   101 		 */
       
   102 		add_postbox_toggles : function (page, args) {
       
   103 			var $handles = $( '.postbox .hndle, .postbox .handlediv' );
       
   104 
       
   105 			this.page = page;
       
   106 			this.init( page, args );
       
   107 
       
   108 			$handles.on( 'click.postboxes', this.handle_click );
       
   109 
       
   110 			/**
       
   111 			 * @since 2.7.0
       
   112 			 */
    35 			$('.postbox .hndle a').click( function(e) {
   113 			$('.postbox .hndle a').click( function(e) {
    36 				e.stopPropagation();
   114 				e.stopPropagation();
    37 			});
   115 			});
    38 
   116 
    39 			$( '.postbox a.dismiss' ).bind( 'click.postboxes', function() {
   117 			/**
       
   118 			 * @summary Hides a postbox.
       
   119 			 *
       
   120 			 * Event handler for the postbox dismiss button. After clicking the button
       
   121 			 * the postbox will be hidden.
       
   122 			 *
       
   123 			 * @since 3.2.0
       
   124 			 *
       
   125 			 * @returns {void}
       
   126 			 */
       
   127 			$( '.postbox a.dismiss' ).on( 'click.postboxes', function( e ) {
    40 				var hide_id = $(this).parents('.postbox').attr('id') + '-hide';
   128 				var hide_id = $(this).parents('.postbox').attr('id') + '-hide';
       
   129 				e.preventDefault();
    41 				$( '#' + hide_id ).prop('checked', false).triggerHandler('click');
   130 				$( '#' + hide_id ).prop('checked', false).triggerHandler('click');
    42 				return false;
   131 			});
    43 			});
   132 
    44 
   133 			/**
       
   134 			 * @summary Hides the postbox element
       
   135 			 *
       
   136 			 * Event handler for the screen options checkboxes. When a checkbox is
       
   137 			 * clicked this function will hide or show the relevant postboxes.
       
   138 			 *
       
   139 			 * @since 2.7.0
       
   140 			 * @fires postboxes#postbox-toggled
       
   141 			 *
       
   142 			 * @returns {void}
       
   143 			 */
    45 			$('.hide-postbox-tog').bind('click.postboxes', function() {
   144 			$('.hide-postbox-tog').bind('click.postboxes', function() {
    46 				var boxId = $(this).val(),
   145 				var $el = $(this),
       
   146 					boxId = $el.val(),
    47 					$postbox = $( '#' + boxId );
   147 					$postbox = $( '#' + boxId );
    48 
   148 
    49 				if ( $(this).prop('checked') ) {
   149 				if ( $el.prop( 'checked' ) ) {
    50 					$postbox.show();
   150 					$postbox.show();
    51 					if ( $.isFunction( postboxes.pbshow ) )
   151 					if ( $.isFunction( postboxes.pbshow ) ) {
    52 						self.pbshow( boxId );
   152 						postboxes.pbshow( boxId );
       
   153 					}
    53 				} else {
   154 				} else {
    54 					$postbox.hide();
   155 					$postbox.hide();
    55 					if ( $.isFunction( postboxes.pbhide ) )
   156 					if ( $.isFunction( postboxes.pbhide ) ) {
    56 						self.pbhide( boxId );
   157 						postboxes.pbhide( boxId );
    57 				}
   158 					}
    58 				self.save_state(page);
   159 				}
    59 				self._mark_area();
   160 
       
   161 				postboxes.save_state( page );
       
   162 				postboxes._mark_area();
       
   163 
       
   164 				/**
       
   165 				 * @since 4.0.0
       
   166 				 * @see postboxes.handle_click
       
   167 				 */
    60 				$document.trigger( 'postbox-toggled', $postbox );
   168 				$document.trigger( 'postbox-toggled', $postbox );
    61 			});
   169 			});
    62 
   170 
       
   171 			/**
       
   172 			 * @summary Changes the amount of columns based on the layout preferences.
       
   173 			 *
       
   174 			 * @since 2.8.0
       
   175 			 *
       
   176 			 * @returns {void}
       
   177 			 */
    63 			$('.columns-prefs input[type="radio"]').bind('click.postboxes', function(){
   178 			$('.columns-prefs input[type="radio"]').bind('click.postboxes', function(){
    64 				var n = parseInt($(this).val(), 10);
   179 				var n = parseInt($(this).val(), 10);
    65 
   180 
    66 				if ( n ) {
   181 				if ( n ) {
    67 					self._pb_edit(n);
   182 					postboxes._pb_edit(n);
    68 					self.save_order(page);
   183 					postboxes.save_order( page );
    69 				}
   184 				}
    70 			});
   185 			});
    71 		},
   186 		},
    72 
   187 
       
   188 		/**
       
   189 		 * @summary Initializes all the postboxes, mainly their sortable behaviour.
       
   190 		 *
       
   191 		 * @since 2.7.0
       
   192 		 * @memberof postboxes
       
   193 		 *
       
   194 		 * @param {string} page The page we are currently on.
       
   195 		 * @param {Object} [args={}] The arguments for the postbox initializer.
       
   196 		 * @param {Function} args.pbshow A callback that is called when a postbox opens.
       
   197 		 * @param {Function} args.pbhide A callback that is called when a postbox
       
   198 		 *                               closes.
       
   199 		 *
       
   200 		 * @returns {void}
       
   201 		 */
    73 		init : function(page, args) {
   202 		init : function(page, args) {
    74 			var isMobile = $(document.body).hasClass('mobile');
   203 			var isMobile = $( document.body ).hasClass( 'mobile' ),
       
   204 				$handleButtons = $( '.postbox .handlediv' );
    75 
   205 
    76 			$.extend( this, args || {} );
   206 			$.extend( this, args || {} );
    77 			$('#wpbody-content').css('overflow','hidden');
   207 			$('#wpbody-content').css('overflow','hidden');
    78 			$('.meta-box-sortables').sortable({
   208 			$('.meta-box-sortables').sortable({
    79 				placeholder: 'sortable-placeholder',
   209 				placeholder: 'sortable-placeholder',
    83 				cursor: 'move',
   213 				cursor: 'move',
    84 				delay: ( isMobile ? 200 : 0 ),
   214 				delay: ( isMobile ? 200 : 0 ),
    85 				distance: 2,
   215 				distance: 2,
    86 				tolerance: 'pointer',
   216 				tolerance: 'pointer',
    87 				forcePlaceholderSize: true,
   217 				forcePlaceholderSize: true,
    88 				helper: 'clone',
   218 				helper: function( event, element ) {
       
   219 					/* `helper: 'clone'` is equivalent to `return element.clone();`
       
   220 					 * Cloning a checked radio and then inserting that clone next to the original
       
   221 					 * radio unchecks the original radio (since only one of the two can be checked).
       
   222 					 * We get around this by renaming the helper's inputs' name attributes so that,
       
   223 					 * when the helper is inserted into the DOM for the sortable, no radios are
       
   224 					 * duplicated, and no original radio gets unchecked.
       
   225 					 */
       
   226 					return element.clone()
       
   227 						.find( ':input' )
       
   228 							.attr( 'name', function( i, currentName ) {
       
   229 								return 'sort_' + parseInt( Math.random() * 100000, 10 ).toString() + '_' + currentName;
       
   230 							} )
       
   231 						.end();
       
   232 				},
    89 				opacity: 0.65,
   233 				opacity: 0.65,
    90 				stop: function() {
   234 				stop: function() {
    91 					if ( $(this).find('#dashboard_browser_nag').is(':visible') && 'dashboard_browser_nag' != this.firstChild.id ) {
   235 					var $el = $( this );
    92 						$(this).sortable('cancel');
   236 
       
   237 					if ( $el.find( '#dashboard_browser_nag' ).is( ':visible' ) && 'dashboard_browser_nag' != this.firstChild.id ) {
       
   238 						$el.sortable('cancel');
    93 						return;
   239 						return;
    94 					}
   240 					}
    95 
   241 
    96 					postboxes.save_order(page);
   242 					postboxes.save_order(page);
    97 				},
   243 				},
    98 				receive: function(e,ui) {
   244 				receive: function(e,ui) {
    99 					if ( 'dashboard_browser_nag' == ui.item[0].id )
   245 					if ( 'dashboard_browser_nag' == ui.item[0].id )
   100 						$(ui.sender).sortable('cancel');
   246 						$(ui.sender).sortable('cancel');
   101 
   247 
   102 					postboxes._mark_area();
   248 					postboxes._mark_area();
       
   249 					$document.trigger( 'postbox-moved', ui.item );
   103 				}
   250 				}
   104 			});
   251 			});
   105 
   252 
   106 			if ( isMobile ) {
   253 			if ( isMobile ) {
   107 				$(document.body).bind('orientationchange.postboxes', function(){ postboxes._pb_change(); });
   254 				$(document.body).bind('orientationchange.postboxes', function(){ postboxes._pb_change(); });
   108 				this._pb_change();
   255 				this._pb_change();
   109 			}
   256 			}
   110 
   257 
   111 			this._mark_area();
   258 			this._mark_area();
   112 		},
   259 
   113 
   260 			// Set the handle buttons `aria-expanded` attribute initial value on page load.
       
   261 			$handleButtons.each( function () {
       
   262 				var $el = $( this );
       
   263 				$el.attr( 'aria-expanded', ! $el.parent( '.postbox' ).hasClass( 'closed' ) );
       
   264 			});
       
   265 		},
       
   266 
       
   267 		/**
       
   268 		 * @summary Saves the state of the postboxes to the server.
       
   269 		 *
       
   270 		 * Saves the state of the postboxes to the server. It sends two lists, one with
       
   271 		 * all the closed postboxes, one with all the hidden postboxes.
       
   272 		 *
       
   273 		 * @since 2.7.0
       
   274 		 * @memberof postboxes
       
   275 		 *
       
   276 		 * @param {string} page The page we are currently on.
       
   277 		 * @returns {void}
       
   278 		 */
   114 		save_state : function(page) {
   279 		save_state : function(page) {
   115 			var closed = $('.postbox').filter('.closed').map(function() { return this.id; }).get().join(','),
   280 			var closed, hidden;
   116 				hidden = $('.postbox').filter(':hidden').map(function() { return this.id; }).get().join(',');
   281 
       
   282 			// Return on the nav-menus.php screen, see #35112.
       
   283 			if ( 'nav-menus' === page ) {
       
   284 				return;
       
   285 			}
       
   286 
       
   287 			closed = $( '.postbox' ).filter( '.closed' ).map( function() { return this.id; } ).get().join( ',' );
       
   288 			hidden = $( '.postbox' ).filter( ':hidden' ).map( function() { return this.id; } ).get().join( ',' );
   117 
   289 
   118 			$.post(ajaxurl, {
   290 			$.post(ajaxurl, {
   119 				action: 'closed-postboxes',
   291 				action: 'closed-postboxes',
   120 				closed: closed,
   292 				closed: closed,
   121 				hidden: hidden,
   293 				hidden: hidden,
   122 				closedpostboxesnonce: jQuery('#closedpostboxesnonce').val(),
   294 				closedpostboxesnonce: jQuery('#closedpostboxesnonce').val(),
   123 				page: page
   295 				page: page
   124 			});
   296 			});
   125 		},
   297 		},
   126 
   298 
       
   299 		/**
       
   300 		 * @summary Saves the order of the postboxes to the server.
       
   301 		 *
       
   302 		 * Saves the order of the postboxes to the server. Sends a list of all postboxes
       
   303 		 * inside a sortable area to the server.
       
   304 		 *
       
   305 		 * @since 2.8.0
       
   306 		 * @memberof postboxes
       
   307 		 *
       
   308 		 * @param {string} page The page we are currently on.
       
   309 		 * @returns {void}
       
   310 		 */
   127 		save_order : function(page) {
   311 		save_order : function(page) {
   128 			var postVars, page_columns = $('.columns-prefs input:checked').val() || 0;
   312 			var postVars, page_columns = $('.columns-prefs input:checked').val() || 0;
   129 
   313 
   130 			postVars = {
   314 			postVars = {
   131 				action: 'meta-box-order',
   315 				action: 'meta-box-order',
   132 				_ajax_nonce: $('#meta-box-order-nonce').val(),
   316 				_ajax_nonce: $('#meta-box-order-nonce').val(),
   133 				page_columns: page_columns,
   317 				page_columns: page_columns,
   134 				page: page
   318 				page: page
   135 			};
   319 			};
       
   320 
   136 			$('.meta-box-sortables').each( function() {
   321 			$('.meta-box-sortables').each( function() {
   137 				postVars[ 'order[' + this.id.split( '-' )[0] + ']' ] = $( this ).sortable( 'toArray' ).join( ',' );
   322 				postVars[ 'order[' + this.id.split( '-' )[0] + ']' ] = $( this ).sortable( 'toArray' ).join( ',' );
   138 			} );
   323 			} );
       
   324 
   139 			$.post( ajaxurl, postVars );
   325 			$.post( ajaxurl, postVars );
   140 		},
   326 		},
   141 
   327 
       
   328 		/**
       
   329 		 * @summary Marks empty postbox areas.
       
   330 		 *
       
   331 		 * Adds a message to empty sortable areas on the dashboard page. Also adds a
       
   332 		 * border around the side area on the post edit screen if there are no postboxes
       
   333 		 * present.
       
   334 		 *
       
   335 		 * @since 3.3.0
       
   336 		 * @memberof postboxes
       
   337 		 * @access private
       
   338 		 *
       
   339 		 * @returns {void}
       
   340 		 */
   142 		_mark_area : function() {
   341 		_mark_area : function() {
   143 			var visible = $('div.postbox:visible').length, side = $('#post-body #side-sortables');
   342 			var visible = $('div.postbox:visible').length, side = $('#post-body #side-sortables');
   144 
   343 
   145 			$( '#dashboard-widgets .meta-box-sortables:visible' ).each( function() {
   344 			$( '#dashboard-widgets .meta-box-sortables:visible' ).each( function() {
   146 				var t = $(this);
   345 				var t = $(this);
   147 
   346 
   148 				if ( visible == 1 || t.children('.postbox:visible').length )
   347 				if ( visible == 1 || t.children('.postbox:visible').length ) {
   149 					t.removeClass('empty-container');
   348 					t.removeClass('empty-container');
   150 				else
   349 				}
       
   350 				else {
   151 					t.addClass('empty-container');
   351 					t.addClass('empty-container');
       
   352 					t.attr('data-emptyString', postBoxL10n.postBoxEmptyString);
       
   353 				}
   152 			});
   354 			});
   153 
   355 
   154 			if ( side.length ) {
   356 			if ( side.length ) {
   155 				if ( side.children('.postbox:visible').length )
   357 				if ( side.children('.postbox:visible').length )
   156 					side.removeClass('empty-container');
   358 					side.removeClass('empty-container');
   157 				else if ( $('#postbox-container-1').css('width') == '280px' )
   359 				else if ( $('#postbox-container-1').css('width') == '280px' )
   158 					side.addClass('empty-container');
   360 					side.addClass('empty-container');
   159 			}
   361 			}
   160 		},
   362 		},
   161 
   363 
       
   364 		/**
       
   365 		 * @summary Changes the amount of columns on the post edit page.
       
   366 		 *
       
   367 		 * @since 3.3.0
       
   368 		 * @memberof postboxes
       
   369 		 * @fires postboxes#postboxes-columnchange
       
   370 		 * @access private
       
   371 		 *
       
   372 		 * @param {number} n The amount of columns to divide the post edit page in.
       
   373 		 * @returns {void}
       
   374 		 */
   162 		_pb_edit : function(n) {
   375 		_pb_edit : function(n) {
   163 			var el = $('.metabox-holder').get(0);
   376 			var el = $('.metabox-holder').get(0);
   164 
   377 
   165 			if ( el ) {
   378 			if ( el ) {
   166 				el.className = el.className.replace(/columns-\d+/, 'columns-' + n);
   379 				el.className = el.className.replace(/columns-\d+/, 'columns-' + n);
   167 			}
   380 			}
   168 
   381 
       
   382 			/**
       
   383 			 * Fires when the amount of columns on the post edit page has been changed.
       
   384 			 *
       
   385 			 * @since 4.0.0
       
   386 			 * @event postboxes#postboxes-columnchange
       
   387 			 */
   169 			$( document ).trigger( 'postboxes-columnchange' );
   388 			$( document ).trigger( 'postboxes-columnchange' );
   170 		},
   389 		},
   171 
   390 
       
   391 		/**
       
   392 		 * @summary Changes the amount of columns the postboxes are in based on the
       
   393 		 *          current orientation of the browser.
       
   394 		 *
       
   395 		 * @since 3.3.0
       
   396 		 * @memberof postboxes
       
   397 		 * @access private
       
   398 		 *
       
   399 		 * @returns {void}
       
   400 		 */
   172 		_pb_change : function() {
   401 		_pb_change : function() {
   173 			var check = $( 'label.columns-prefs-1 input[type="radio"]' );
   402 			var check = $( 'label.columns-prefs-1 input[type="radio"]' );
   174 
   403 
   175 			switch ( window.orientation ) {
   404 			switch ( window.orientation ) {
   176 				case 90:
   405 				case 90:
   189 					break;
   418 					break;
   190 			}
   419 			}
   191 		},
   420 		},
   192 
   421 
   193 		/* Callbacks */
   422 		/* Callbacks */
       
   423 
       
   424 		/**
       
   425 		 * @since 2.7.0
       
   426 		 * @memberof postboxes
       
   427 		 * @access public
       
   428 		 * @property {Function|boolean} pbshow A callback that is called when a postbox
       
   429 		 *                                     is opened.
       
   430 		 */
   194 		pbshow : false,
   431 		pbshow : false,
   195 
   432 
       
   433 		/**
       
   434 		 * @since 2.7.0
       
   435 		 * @memberof postboxes
       
   436 		 * @access public
       
   437 		 * @property {Function|boolean} pbhide A callback that is called when a postbox
       
   438 		 *                                     is closed.
       
   439 		 */
   196 		pbhide : false
   440 		pbhide : false
   197 	};
   441 	};
   198 
   442 
   199 }(jQuery));
   443 }(jQuery));