30 * Opens or closes the postbox. Expects `this` to equal the clicked element. |
31 * Opens or closes the postbox. Expects `this` to equal the clicked element. |
31 * Calls postboxes.pbshow if the postbox has been opened, calls postboxes.pbhide |
32 * Calls postboxes.pbshow if the postbox has been opened, calls postboxes.pbhide |
32 * if the postbox has been closed. |
33 * if the postbox has been closed. |
33 * |
34 * |
34 * @since 4.4.0 |
35 * @since 4.4.0 |
35 * @memberof postboxes |
36 * |
|
37 * @memberof postboxes |
|
38 * |
36 * @fires postboxes#postbox-toggled |
39 * @fires postboxes#postbox-toggled |
37 * |
40 * |
38 * @returns {void} |
41 * @return {void} |
39 */ |
42 */ |
40 handle_click : function () { |
43 handle_click : function () { |
41 var $el = $( this ), |
44 var $el = $( this ), |
42 p = $el.parent( '.postbox' ), |
45 p = $el.closest( '.postbox' ), |
43 id = p.attr( 'id' ), |
46 id = p.attr( 'id' ), |
44 ariaExpandedValue; |
47 ariaExpandedValue; |
45 |
48 |
46 if ( 'dashboard_browser_nag' === id ) { |
49 if ( 'dashboard_browser_nag' === id ) { |
47 return; |
50 return; |
48 } |
51 } |
49 |
52 |
50 p.toggleClass( 'closed' ); |
53 p.toggleClass( 'closed' ); |
51 |
|
52 ariaExpandedValue = ! p.hasClass( 'closed' ); |
54 ariaExpandedValue = ! p.hasClass( 'closed' ); |
53 |
55 |
54 if ( $el.hasClass( 'handlediv' ) ) { |
56 if ( $el.hasClass( 'handlediv' ) ) { |
55 // The handle button was clicked. |
57 // The handle button was clicked. |
56 $el.attr( 'aria-expanded', ariaExpandedValue ); |
58 $el.attr( 'aria-expanded', ariaExpandedValue ); |
85 */ |
87 */ |
86 $document.trigger( 'postbox-toggled', p ); |
88 $document.trigger( 'postbox-toggled', p ); |
87 }, |
89 }, |
88 |
90 |
89 /** |
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.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.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 /** |
90 * Adds event handlers to all postboxes and screen option on the current page. |
243 * Adds event handlers to all postboxes and screen option on the current page. |
91 * |
244 * |
92 * @since 2.7.0 |
245 * @since 2.7.0 |
|
246 * |
93 * @memberof postboxes |
247 * @memberof postboxes |
94 * |
248 * |
95 * @param {string} page The page we are currently on. |
249 * @param {string} page The page we are currently on. |
96 * @param {Object} [args] |
250 * @param {Object} [args] |
97 * @param {Function} args.pbshow A callback that is called when a postbox opens. |
251 * @param {Function} args.pbshow A callback that is called when a postbox opens. |
98 * @param {Function} args.pbhide A callback that is called when a postbox closes. |
252 * @param {Function} args.pbhide A callback that is called when a postbox closes. |
99 * @returns {void} |
253 * @return {void} |
100 */ |
254 */ |
101 add_postbox_toggles : function (page, args) { |
255 add_postbox_toggles : function (page, args) { |
102 var $handles = $( '.postbox .hndle, .postbox .handlediv' ); |
256 var $handles = $( '.postbox .hndle, .postbox .handlediv' ), |
|
257 $orderButtons = $( '.postbox .handle-order-higher, .postbox .handle-order-lower' ); |
103 |
258 |
104 this.page = page; |
259 this.page = page; |
105 this.init( page, args ); |
260 this.init( page, args ); |
106 |
261 |
107 $handles.on( 'click.postboxes', this.handle_click ); |
262 $handles.on( 'click.postboxes', this.handle_click ); |
|
263 |
|
264 // Handle the order of the postboxes. |
|
265 $orderButtons.on( 'click.postboxes', this.handleOrder ); |
108 |
266 |
109 /** |
267 /** |
110 * @since 2.7.0 |
268 * @since 2.7.0 |
111 */ |
269 */ |
112 $('.postbox .hndle a').click( function(e) { |
270 $('.postbox .hndle a').click( function(e) { |
188 |
348 |
189 /** |
349 /** |
190 * Initializes all the postboxes, mainly their sortable behaviour. |
350 * Initializes all the postboxes, mainly their sortable behaviour. |
191 * |
351 * |
192 * @since 2.7.0 |
352 * @since 2.7.0 |
|
353 * |
193 * @memberof postboxes |
354 * @memberof postboxes |
194 * |
355 * |
195 * @param {string} page The page we are currently on. |
356 * @param {string} page The page we are currently on. |
196 * @param {Object} [args={}] The arguments for the postbox initializer. |
357 * @param {Object} [args={}] The arguments for the postbox initializer. |
197 * @param {Function} args.pbshow A callback that is called when a postbox opens. |
358 * @param {Function} args.pbshow A callback that is called when a postbox opens. |
198 * @param {Function} args.pbhide A callback that is called when a postbox |
359 * @param {Function} args.pbhide A callback that is called when a postbox |
199 * closes. |
360 * closes. |
200 * |
361 * |
201 * @returns {void} |
362 * @return {void} |
202 */ |
363 */ |
203 init : function(page, args) { |
364 init : function(page, args) { |
204 var isMobile = $( document.body ).hasClass( 'mobile' ), |
365 var isMobile = $( document.body ).hasClass( 'mobile' ), |
205 $handleButtons = $( '.postbox .handlediv' ); |
366 $handleButtons = $( '.postbox .handlediv' ); |
206 |
367 |
207 $.extend( this, args || {} ); |
368 $.extend( this, args || {} ); |
208 $('#wpbody-content').css('overflow','hidden'); |
|
209 $('.meta-box-sortables').sortable({ |
369 $('.meta-box-sortables').sortable({ |
210 placeholder: 'sortable-placeholder', |
370 placeholder: 'sortable-placeholder', |
211 connectWith: '.meta-box-sortables', |
371 connectWith: '.meta-box-sortables', |
212 items: '.postbox', |
372 items: '.postbox', |
213 handle: '.hndle', |
373 handle: '.hndle', |
320 |
494 |
321 $('.meta-box-sortables').each( function() { |
495 $('.meta-box-sortables').each( function() { |
322 postVars[ 'order[' + this.id.split( '-' )[0] + ']' ] = $( this ).sortable( 'toArray' ).join( ',' ); |
496 postVars[ 'order[' + this.id.split( '-' )[0] + ']' ] = $( this ).sortable( 'toArray' ).join( ',' ); |
323 } ); |
497 } ); |
324 |
498 |
325 $.post( ajaxurl, postVars ); |
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 ); |
326 }, |
508 }, |
327 |
509 |
328 /** |
510 /** |
329 * Marks empty postbox areas. |
511 * Marks empty postbox areas. |
330 * |
512 * |
331 * Adds a message to empty sortable areas on the dashboard page. Also adds a |
513 * 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 |
514 * border around the side area on the post edit screen if there are no postboxes |
333 * present. |
515 * present. |
334 * |
516 * |
335 * @since 3.3.0 |
517 * @since 3.3.0 |
336 * @memberof postboxes |
|
337 * @access private |
518 * @access private |
338 * |
519 * |
339 * @returns {void} |
520 * @memberof postboxes |
|
521 * |
|
522 * @return {void} |
340 */ |
523 */ |
341 _mark_area : function() { |
524 _mark_area : function() { |
342 var visible = $('div.postbox:visible').length, side = $('#post-body #side-sortables'); |
525 var visible = $( 'div.postbox:visible' ).length, |
343 |
526 visibleSortables = $( '#dashboard-widgets .meta-box-sortables:visible, #post-body .meta-box-sortables:visible' ), |
344 $( '#dashboard-widgets .meta-box-sortables:visible' ).each( function() { |
527 areAllVisibleSortablesEmpty = true; |
|
528 |
|
529 visibleSortables.each( function() { |
345 var t = $(this); |
530 var t = $(this); |
346 |
531 |
347 if ( visible == 1 || t.children('.postbox:visible').length ) { |
532 if ( visible == 1 || t.children( '.postbox:visible' ).length ) { |
348 t.removeClass('empty-container'); |
533 t.removeClass('empty-container'); |
|
534 areAllVisibleSortablesEmpty = false; |
349 } |
535 } |
350 else { |
536 else { |
351 t.addClass('empty-container'); |
537 t.addClass('empty-container'); |
352 t.attr('data-emptyString', postBoxL10n.postBoxEmptyString); |
538 } |
353 } |
539 }); |
354 }); |
540 |
355 |
541 postboxes.updateEmptySortablesText( visibleSortables, areAllVisibleSortablesEmpty ); |
356 if ( side.length ) { |
542 }, |
357 if ( side.children('.postbox:visible').length ) |
543 |
358 side.removeClass('empty-container'); |
544 /** |
359 else if ( $('#postbox-container-1').css('width') == '280px' ) |
545 * Updates the text for the empty sortable areas on the Dashboard. |
360 side.addClass('empty-container'); |
546 * |
361 } |
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 } ); |
362 }, |
567 }, |
363 |
568 |
364 /** |
569 /** |
365 * Changes the amount of columns on the post edit page. |
570 * Changes the amount of columns on the post edit page. |
366 * |
571 * |
367 * @since 3.3.0 |
572 * @since 3.3.0 |
368 * @memberof postboxes |
573 * @access private |
|
574 * |
|
575 * @memberof postboxes |
|
576 * |
369 * @fires postboxes#postboxes-columnchange |
577 * @fires postboxes#postboxes-columnchange |
370 * @access private |
|
371 * |
578 * |
372 * @param {number} n The amount of columns to divide the post edit page in. |
579 * @param {number} n The amount of columns to divide the post edit page in. |
373 * @returns {void} |
580 * @return {void} |
374 */ |
581 */ |
375 _pb_edit : function(n) { |
582 _pb_edit : function(n) { |
376 var el = $('.metabox-holder').get(0); |
583 var el = $('.metabox-holder').get(0); |
377 |
584 |
378 if ( el ) { |
585 if ( el ) { |