[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 /** 2 * @output wp-admin/js/widgets.js 3 */ 4 5 /* global ajaxurl, isRtl, wpWidgets */ 6 7 (function($) { 8 var $document = $( document ); 9 10 window.wpWidgets = { 11 /** 12 * A closed Sidebar that gets a Widget dragged over it. 13 * 14 * @var {element|null} 15 */ 16 hoveredSidebar: null, 17 18 /** 19 * Lookup of which widgets have had change events triggered. 20 * 21 * @var {object} 22 */ 23 dirtyWidgets: {}, 24 25 init : function() { 26 var rem, the_id, 27 self = this, 28 chooser = $('.widgets-chooser'), 29 selectSidebar = chooser.find('.widgets-chooser-sidebars'), 30 sidebars = $('div.widgets-sortables'), 31 isRTL = !! ( 'undefined' !== typeof isRtl && isRtl ); 32 33 // Handle the widgets containers in the right column. 34 $( '#widgets-right .sidebar-name' ) 35 /* 36 * Toggle the widgets containers when clicked and update the toggle 37 * button `aria-expanded` attribute value. 38 */ 39 .on( 'click', function() { 40 var $this = $( this ), 41 $wrap = $this.closest( '.widgets-holder-wrap '), 42 $toggle = $this.find( '.handlediv' ); 43 44 if ( $wrap.hasClass( 'closed' ) ) { 45 $wrap.removeClass( 'closed' ); 46 $toggle.attr( 'aria-expanded', 'true' ); 47 // Refresh the jQuery UI sortable items. 48 $this.parent().sortable( 'refresh' ); 49 } else { 50 $wrap.addClass( 'closed' ); 51 $toggle.attr( 'aria-expanded', 'false' ); 52 } 53 54 // Update the admin menu "sticky" state. 55 $document.triggerHandler( 'wp-pin-menu' ); 56 }) 57 /* 58 * Set the initial `aria-expanded` attribute value on the widgets 59 * containers toggle button. The first one is expanded by default. 60 */ 61 .find( '.handlediv' ).each( function( index ) { 62 if ( 0 === index ) { 63 // jQuery equivalent of `continue` within an `each()` loop. 64 return; 65 } 66 67 $( this ).attr( 'aria-expanded', 'false' ); 68 }); 69 70 // Show AYS dialog when there are unsaved widget changes. 71 $( window ).on( 'beforeunload.widgets', function( event ) { 72 var dirtyWidgetIds = [], unsavedWidgetsElements; 73 $.each( self.dirtyWidgets, function( widgetId, dirty ) { 74 if ( dirty ) { 75 dirtyWidgetIds.push( widgetId ); 76 } 77 }); 78 if ( 0 !== dirtyWidgetIds.length ) { 79 unsavedWidgetsElements = $( '#widgets-right' ).find( '.widget' ).filter( function() { 80 return -1 !== dirtyWidgetIds.indexOf( $( this ).prop( 'id' ).replace( /^widget-\d+_/, '' ) ); 81 }); 82 unsavedWidgetsElements.each( function() { 83 if ( ! $( this ).hasClass( 'open' ) ) { 84 $( this ).find( '.widget-title-action:first' ).trigger( 'click' ); 85 } 86 }); 87 88 // Bring the first unsaved widget into view and focus on the first tabbable field. 89 unsavedWidgetsElements.first().each( function() { 90 if ( this.scrollIntoViewIfNeeded ) { 91 this.scrollIntoViewIfNeeded(); 92 } else { 93 this.scrollIntoView(); 94 } 95 $( this ).find( '.widget-inside :tabbable:first' ).trigger( 'focus' ); 96 } ); 97 98 event.returnValue = wp.i18n.__( 'The changes you made will be lost if you navigate away from this page.' ); 99 return event.returnValue; 100 } 101 }); 102 103 // Handle the widgets containers in the left column. 104 $( '#widgets-left .sidebar-name' ).on( 'click', function() { 105 var $wrap = $( this ).closest( '.widgets-holder-wrap' ); 106 107 $wrap 108 .toggleClass( 'closed' ) 109 .find( '.handlediv' ).attr( 'aria-expanded', ! $wrap.hasClass( 'closed' ) ); 110 111 // Update the admin menu "sticky" state. 112 $document.triggerHandler( 'wp-pin-menu' ); 113 }); 114 115 $(document.body).on('click.widgets-toggle', function(e) { 116 var target = $(e.target), css = {}, 117 widget, inside, targetWidth, widgetWidth, margin, saveButton, widgetId, 118 toggleBtn = target.closest( '.widget' ).find( '.widget-top button.widget-action' ); 119 120 if ( target.parents('.widget-top').length && ! target.parents('#available-widgets').length ) { 121 widget = target.closest('div.widget'); 122 inside = widget.children('.widget-inside'); 123 targetWidth = parseInt( widget.find('input.widget-width').val(), 10 ); 124 widgetWidth = widget.parent().width(); 125 widgetId = inside.find( '.widget-id' ).val(); 126 127 // Save button is initially disabled, but is enabled when a field is changed. 128 if ( ! widget.data( 'dirty-state-initialized' ) ) { 129 saveButton = inside.find( '.widget-control-save' ); 130 saveButton.prop( 'disabled', true ).val( wp.i18n.__( 'Saved' ) ); 131 inside.on( 'input change', function() { 132 self.dirtyWidgets[ widgetId ] = true; 133 widget.addClass( 'widget-dirty' ); 134 saveButton.prop( 'disabled', false ).val( wp.i18n.__( 'Save' ) ); 135 }); 136 widget.data( 'dirty-state-initialized', true ); 137 } 138 139 if ( inside.is(':hidden') ) { 140 if ( targetWidth > 250 && ( targetWidth + 30 > widgetWidth ) && widget.closest('div.widgets-sortables').length ) { 141 if ( widget.closest('div.widget-liquid-right').length ) { 142 margin = isRTL ? 'margin-right' : 'margin-left'; 143 } else { 144 margin = isRTL ? 'margin-left' : 'margin-right'; 145 } 146 147 css[ margin ] = widgetWidth - ( targetWidth + 30 ) + 'px'; 148 widget.css( css ); 149 } 150 /* 151 * Don't change the order of attributes changes and animation: 152 * it's important for screen readers, see ticket #31476. 153 */ 154 toggleBtn.attr( 'aria-expanded', 'true' ); 155 inside.slideDown( 'fast', function() { 156 widget.addClass( 'open' ); 157 }); 158 } else { 159 /* 160 * Don't change the order of attributes changes and animation: 161 * it's important for screen readers, see ticket #31476. 162 */ 163 toggleBtn.attr( 'aria-expanded', 'false' ); 164 inside.slideUp( 'fast', function() { 165 widget.attr( 'style', '' ); 166 widget.removeClass( 'open' ); 167 }); 168 } 169 } else if ( target.hasClass('widget-control-save') ) { 170 wpWidgets.save( target.closest('div.widget'), 0, 1, 0 ); 171 e.preventDefault(); 172 } else if ( target.hasClass('widget-control-remove') ) { 173 wpWidgets.save( target.closest('div.widget'), 1, 1, 0 ); 174 } else if ( target.hasClass('widget-control-close') ) { 175 widget = target.closest('div.widget'); 176 widget.removeClass( 'open' ); 177 toggleBtn.attr( 'aria-expanded', 'false' ); 178 wpWidgets.close( widget ); 179 } else if ( target.attr( 'id' ) === 'inactive-widgets-control-remove' ) { 180 wpWidgets.removeInactiveWidgets(); 181 e.preventDefault(); 182 } 183 }); 184 185 sidebars.children('.widget').each( function() { 186 var $this = $(this); 187 188 wpWidgets.appendTitle( this ); 189 190 if ( $this.find( 'p.widget-error' ).length ) { 191 $this.find( '.widget-action' ).trigger( 'click' ).attr( 'aria-expanded', 'true' ); 192 } 193 }); 194 195 $('#widget-list').children('.widget').draggable({ 196 connectToSortable: 'div.widgets-sortables', 197 handle: '> .widget-top > .widget-title', 198 distance: 2, 199 helper: 'clone', 200 zIndex: 101, 201 containment: '#wpwrap', 202 refreshPositions: true, 203 start: function( event, ui ) { 204 var chooser = $(this).find('.widgets-chooser'); 205 206 ui.helper.find('div.widget-description').hide(); 207 the_id = this.id; 208 209 if ( chooser.length ) { 210 // Hide the chooser and move it out of the widget. 211 $( '#wpbody-content' ).append( chooser.hide() ); 212 // Delete the cloned chooser from the drag helper. 213 ui.helper.find('.widgets-chooser').remove(); 214 self.clearWidgetSelection(); 215 } 216 }, 217 stop: function() { 218 if ( rem ) { 219 $(rem).hide(); 220 } 221 222 rem = ''; 223 } 224 }); 225 226 /** 227 * Opens and closes previously closed Sidebars when Widgets are dragged over/out of them. 228 */ 229 sidebars.droppable( { 230 tolerance: 'intersect', 231 232 /** 233 * Open Sidebar when a Widget gets dragged over it. 234 * 235 * @ignore 236 * 237 * @param {Object} event jQuery event object. 238 */ 239 over: function( event ) { 240 var $wrap = $( event.target ).parent(); 241 242 if ( wpWidgets.hoveredSidebar && ! $wrap.is( wpWidgets.hoveredSidebar ) ) { 243 // Close the previous Sidebar as the Widget has been dragged onto another Sidebar. 244 wpWidgets.closeSidebar( event ); 245 } 246 247 if ( $wrap.hasClass( 'closed' ) ) { 248 wpWidgets.hoveredSidebar = $wrap; 249 $wrap 250 .removeClass( 'closed' ) 251 .find( '.handlediv' ).attr( 'aria-expanded', 'true' ); 252 } 253 254 $( this ).sortable( 'refresh' ); 255 }, 256 257 /** 258 * Close Sidebar when the Widget gets dragged out of it. 259 * 260 * @ignore 261 * 262 * @param {Object} event jQuery event object. 263 */ 264 out: function( event ) { 265 if ( wpWidgets.hoveredSidebar ) { 266 wpWidgets.closeSidebar( event ); 267 } 268 } 269 } ); 270 271 sidebars.sortable({ 272 placeholder: 'widget-placeholder', 273 items: '> .widget', 274 handle: '> .widget-top > .widget-title', 275 cursor: 'move', 276 distance: 2, 277 containment: '#wpwrap', 278 tolerance: 'pointer', 279 refreshPositions: true, 280 start: function( event, ui ) { 281 var height, $this = $(this), 282 $wrap = $this.parent(), 283 inside = ui.item.children('.widget-inside'); 284 285 if ( inside.css('display') === 'block' ) { 286 ui.item.removeClass('open'); 287 ui.item.find( '.widget-top button.widget-action' ).attr( 'aria-expanded', 'false' ); 288 inside.hide(); 289 $(this).sortable('refreshPositions'); 290 } 291 292 if ( ! $wrap.hasClass('closed') ) { 293 // Lock all open sidebars min-height when starting to drag. 294 // Prevents jumping when dragging a widget from an open sidebar to a closed sidebar below. 295 height = ui.item.hasClass('ui-draggable') ? $this.height() : 1 + $this.height(); 296 $this.css( 'min-height', height + 'px' ); 297 } 298 }, 299 300 stop: function( event, ui ) { 301 var addNew, widgetNumber, $sidebar, $children, child, item, 302 $widget = ui.item, 303 id = the_id; 304 305 // Reset the var to hold a previously closed sidebar. 306 wpWidgets.hoveredSidebar = null; 307 308 if ( $widget.hasClass('deleting') ) { 309 wpWidgets.save( $widget, 1, 0, 1 ); // Delete widget. 310 $widget.remove(); 311 return; 312 } 313 314 addNew = $widget.find('input.add_new').val(); 315 widgetNumber = $widget.find('input.multi_number').val(); 316 317 $widget.attr( 'style', '' ).removeClass('ui-draggable'); 318 the_id = ''; 319 320 if ( addNew ) { 321 if ( 'multi' === addNew ) { 322 $widget.html( 323 $widget.html().replace( /<[^<>]+>/g, function( tag ) { 324 return tag.replace( /__i__|%i%/g, widgetNumber ); 325 }) 326 ); 327 328 $widget.attr( 'id', id.replace( '__i__', widgetNumber ) ); 329 widgetNumber++; 330 331 $( 'div#' + id ).find( 'input.multi_number' ).val( widgetNumber ); 332 } else if ( 'single' === addNew ) { 333 $widget.attr( 'id', 'new-' + id ); 334 rem = 'div#' + id; 335 } 336 337 wpWidgets.save( $widget, 0, 0, 1 ); 338 $widget.find('input.add_new').val(''); 339 $document.trigger( 'widget-added', [ $widget ] ); 340 } 341 342 $sidebar = $widget.parent(); 343 344 if ( $sidebar.parent().hasClass('closed') ) { 345 $sidebar.parent() 346 .removeClass( 'closed' ) 347 .find( '.handlediv' ).attr( 'aria-expanded', 'true' ); 348 349 $children = $sidebar.children('.widget'); 350 351 // Make sure the dropped widget is at the top. 352 if ( $children.length > 1 ) { 353 child = $children.get(0); 354 item = $widget.get(0); 355 356 if ( child.id && item.id && child.id !== item.id ) { 357 $( child ).before( $widget ); 358 } 359 } 360 } 361 362 if ( addNew ) { 363 $widget.find( '.widget-action' ).trigger( 'click' ); 364 } else { 365 wpWidgets.saveOrder( $sidebar.attr('id') ); 366 } 367 }, 368 369 activate: function() { 370 $(this).parent().addClass( 'widget-hover' ); 371 }, 372 373 deactivate: function() { 374 // Remove all min-height added on "start". 375 $(this).css( 'min-height', '' ).parent().removeClass( 'widget-hover' ); 376 }, 377 378 receive: function( event, ui ) { 379 var $sender = $( ui.sender ); 380 381 // Don't add more widgets to orphaned sidebars. 382 if ( this.id.indexOf('orphaned_widgets') > -1 ) { 383 $sender.sortable('cancel'); 384 return; 385 } 386 387 // If the last widget was moved out of an orphaned sidebar, close and remove it. 388 if ( $sender.attr('id').indexOf('orphaned_widgets') > -1 && ! $sender.children('.widget').length ) { 389 $sender.parents('.orphan-sidebar').slideUp( 400, function(){ $(this).remove(); } ); 390 } 391 } 392 }).sortable( 'option', 'connectWith', 'div.widgets-sortables' ); 393 394 $('#available-widgets').droppable({ 395 tolerance: 'pointer', 396 accept: function(o){ 397 return $(o).parent().attr('id') !== 'widget-list'; 398 }, 399 drop: function(e,ui) { 400 ui.draggable.addClass('deleting'); 401 $('#removing-widget').hide().children('span').empty(); 402 }, 403 over: function(e,ui) { 404 ui.draggable.addClass('deleting'); 405 $('div.widget-placeholder').hide(); 406 407 if ( ui.draggable.hasClass('ui-sortable-helper') ) { 408 $('#removing-widget').show().children('span') 409 .html( ui.draggable.find( 'div.widget-title' ).children( 'h3' ).html() ); 410 } 411 }, 412 out: function(e,ui) { 413 ui.draggable.removeClass('deleting'); 414 $('div.widget-placeholder').show(); 415 $('#removing-widget').hide().children('span').empty(); 416 } 417 }); 418 419 // Area Chooser. 420 $( '#widgets-right .widgets-holder-wrap' ).each( function( index, element ) { 421 var $element = $( element ), 422 name = $element.find( '.sidebar-name h2' ).text() || '', 423 ariaLabel = $element.find( '.sidebar-name' ).data( 'add-to' ), 424 id = $element.find( '.widgets-sortables' ).attr( 'id' ), 425 li = $( '<li>' ), 426 button = $( '<button>', { 427 type: 'button', 428 'aria-pressed': 'false', 429 'class': 'widgets-chooser-button', 430 'aria-label': ariaLabel 431 } ).text( name.toString().trim() ); 432 433 li.append( button ); 434 435 if ( index === 0 ) { 436 li.addClass( 'widgets-chooser-selected' ); 437 button.attr( 'aria-pressed', 'true' ); 438 } 439 440 selectSidebar.append( li ); 441 li.data( 'sidebarId', id ); 442 }); 443 444 $( '#available-widgets .widget .widget-top' ).on( 'click.widgets-chooser', function() { 445 var $widget = $( this ).closest( '.widget' ), 446 toggleButton = $( this ).find( '.widget-action' ), 447 chooserButtons = selectSidebar.find( '.widgets-chooser-button' ); 448 449 if ( $widget.hasClass( 'widget-in-question' ) || $( '#widgets-left' ).hasClass( 'chooser' ) ) { 450 toggleButton.attr( 'aria-expanded', 'false' ); 451 self.closeChooser(); 452 } else { 453 // Open the chooser. 454 self.clearWidgetSelection(); 455 $( '#widgets-left' ).addClass( 'chooser' ); 456 // Add CSS class and insert the chooser after the widget description. 457 $widget.addClass( 'widget-in-question' ).children( '.widget-description' ).after( chooser ); 458 // Open the chooser with a slide down animation. 459 chooser.slideDown( 300, function() { 460 // Update the toggle button aria-expanded attribute after previous DOM manipulations. 461 toggleButton.attr( 'aria-expanded', 'true' ); 462 }); 463 464 chooserButtons.on( 'click.widgets-chooser', function() { 465 selectSidebar.find( '.widgets-chooser-selected' ).removeClass( 'widgets-chooser-selected' ); 466 chooserButtons.attr( 'aria-pressed', 'false' ); 467 $( this ) 468 .attr( 'aria-pressed', 'true' ) 469 .closest( 'li' ).addClass( 'widgets-chooser-selected' ); 470 } ); 471 } 472 }); 473 474 // Add event handlers. 475 chooser.on( 'click.widgets-chooser', function( event ) { 476 var $target = $( event.target ); 477 478 if ( $target.hasClass('button-primary') ) { 479 self.addWidget( chooser ); 480 self.closeChooser(); 481 } else if ( $target.hasClass( 'widgets-chooser-cancel' ) ) { 482 self.closeChooser(); 483 } 484 }).on( 'keyup.widgets-chooser', function( event ) { 485 if ( event.which === $.ui.keyCode.ESCAPE ) { 486 self.closeChooser(); 487 } 488 }); 489 }, 490 491 saveOrder : function( sidebarId ) { 492 var data = { 493 action: 'widgets-order', 494 savewidgets: $('#_wpnonce_widgets').val(), 495 sidebars: [] 496 }; 497 498 if ( sidebarId ) { 499 $( '#' + sidebarId ).find( '.spinner:first' ).addClass( 'is-active' ); 500 } 501 502 $('div.widgets-sortables').each( function() { 503 if ( $(this).sortable ) { 504 data['sidebars[' + $(this).attr('id') + ']'] = $(this).sortable('toArray').join(','); 505 } 506 }); 507 508 $.post( ajaxurl, data, function() { 509 $( '#inactive-widgets-control-remove' ).prop( 'disabled' , ! $( '#wp_inactive_widgets .widget' ).length ); 510 $( '.spinner' ).removeClass( 'is-active' ); 511 }); 512 }, 513 514 save : function( widget, del, animate, order ) { 515 var self = this, data, a, 516 sidebarId = widget.closest( 'div.widgets-sortables' ).attr( 'id' ), 517 form = widget.find( 'form' ), 518 isAdd = widget.find( 'input.add_new' ).val(); 519 520 if ( ! del && ! isAdd && form.prop( 'checkValidity' ) && ! form[0].checkValidity() ) { 521 return; 522 } 523 524 data = form.serialize(); 525 526 widget = $(widget); 527 $( '.spinner', widget ).addClass( 'is-active' ); 528 529 a = { 530 action: 'save-widget', 531 savewidgets: $('#_wpnonce_widgets').val(), 532 sidebar: sidebarId 533 }; 534 535 if ( del ) { 536 a.delete_widget = 1; 537 } 538 539 data += '&' + $.param(a); 540 541 $.post( ajaxurl, data, function(r) { 542 var id = $('input.widget-id', widget).val(); 543 544 if ( del ) { 545 if ( ! $('input.widget_number', widget).val() ) { 546 $('#available-widgets').find('input.widget-id').each(function(){ 547 if ( $(this).val() === id ) { 548 $(this).closest('div.widget').show(); 549 } 550 }); 551 } 552 553 if ( animate ) { 554 order = 0; 555 widget.slideUp( 'fast', function() { 556 $( this ).remove(); 557 wpWidgets.saveOrder(); 558 delete self.dirtyWidgets[ id ]; 559 }); 560 } else { 561 widget.remove(); 562 delete self.dirtyWidgets[ id ]; 563 564 if ( sidebarId === 'wp_inactive_widgets' ) { 565 $( '#inactive-widgets-control-remove' ).prop( 'disabled' , ! $( '#wp_inactive_widgets .widget' ).length ); 566 } 567 } 568 } else { 569 $( '.spinner' ).removeClass( 'is-active' ); 570 if ( r && r.length > 2 ) { 571 $( 'div.widget-content', widget ).html( r ); 572 wpWidgets.appendTitle( widget ); 573 574 // Re-disable the save button. 575 widget.find( '.widget-control-save' ).prop( 'disabled', true ).val( wp.i18n.__( 'Saved' ) ); 576 577 widget.removeClass( 'widget-dirty' ); 578 579 // Clear the dirty flag from the widget. 580 delete self.dirtyWidgets[ id ]; 581 582 $document.trigger( 'widget-updated', [ widget ] ); 583 584 if ( sidebarId === 'wp_inactive_widgets' ) { 585 $( '#inactive-widgets-control-remove' ).prop( 'disabled' , ! $( '#wp_inactive_widgets .widget' ).length ); 586 } 587 } 588 } 589 590 if ( order ) { 591 wpWidgets.saveOrder(); 592 } 593 }); 594 }, 595 596 removeInactiveWidgets : function() { 597 var $element = $( '.remove-inactive-widgets' ), self = this, a, data; 598 599 $( '.spinner', $element ).addClass( 'is-active' ); 600 601 a = { 602 action : 'delete-inactive-widgets', 603 removeinactivewidgets : $( '#_wpnonce_remove_inactive_widgets' ).val() 604 }; 605 606 data = $.param( a ); 607 608 $.post( ajaxurl, data, function() { 609 $( '#wp_inactive_widgets .widget' ).each(function() { 610 var $widget = $( this ); 611 delete self.dirtyWidgets[ $widget.find( 'input.widget-id' ).val() ]; 612 $widget.remove(); 613 }); 614 $( '#inactive-widgets-control-remove' ).prop( 'disabled', true ); 615 $( '.spinner', $element ).removeClass( 'is-active' ); 616 } ); 617 }, 618 619 appendTitle : function(widget) { 620 var title = $('input[id*="-title"]', widget).val() || ''; 621 622 if ( title ) { 623 title = ': ' + title.replace(/<[^<>]+>/g, '').replace(/</g, '<').replace(/>/g, '>'); 624 } 625 626 $(widget).children('.widget-top').children('.widget-title').children() 627 .children('.in-widget-title').html(title); 628 629 }, 630 631 close : function(widget) { 632 widget.children('.widget-inside').slideUp('fast', function() { 633 widget.attr( 'style', '' ) 634 .find( '.widget-top button.widget-action' ) 635 .attr( 'aria-expanded', 'false' ) 636 .focus(); 637 }); 638 }, 639 640 addWidget: function( chooser ) { 641 var widget, widgetId, add, n, viewportTop, viewportBottom, sidebarBounds, 642 sidebarId = chooser.find( '.widgets-chooser-selected' ).data('sidebarId'), 643 sidebar = $( '#' + sidebarId ); 644 645 widget = $('#available-widgets').find('.widget-in-question').clone(); 646 widgetId = widget.attr('id'); 647 add = widget.find( 'input.add_new' ).val(); 648 n = widget.find( 'input.multi_number' ).val(); 649 650 // Remove the cloned chooser from the widget. 651 widget.find('.widgets-chooser').remove(); 652 653 if ( 'multi' === add ) { 654 widget.html( 655 widget.html().replace( /<[^<>]+>/g, function(m) { 656 return m.replace( /__i__|%i%/g, n ); 657 }) 658 ); 659 660 widget.attr( 'id', widgetId.replace( '__i__', n ) ); 661 n++; 662 $( '#' + widgetId ).find('input.multi_number').val(n); 663 } else if ( 'single' === add ) { 664 widget.attr( 'id', 'new-' + widgetId ); 665 $( '#' + widgetId ).hide(); 666 } 667 668 // Open the widgets container. 669 sidebar.closest( '.widgets-holder-wrap' ) 670 .removeClass( 'closed' ) 671 .find( '.handlediv' ).attr( 'aria-expanded', 'true' ); 672 673 sidebar.append( widget ); 674 sidebar.sortable('refresh'); 675 676 wpWidgets.save( widget, 0, 0, 1 ); 677 // No longer "new" widget. 678 widget.find( 'input.add_new' ).val(''); 679 680 $document.trigger( 'widget-added', [ widget ] ); 681 682 /* 683 * Check if any part of the sidebar is visible in the viewport. If it is, don't scroll. 684 * Otherwise, scroll up to so the sidebar is in view. 685 * 686 * We do this by comparing the top and bottom, of the sidebar so see if they are within 687 * the bounds of the viewport. 688 */ 689 viewportTop = $(window).scrollTop(); 690 viewportBottom = viewportTop + $(window).height(); 691 sidebarBounds = sidebar.offset(); 692 693 sidebarBounds.bottom = sidebarBounds.top + sidebar.outerHeight(); 694 695 if ( viewportTop > sidebarBounds.bottom || viewportBottom < sidebarBounds.top ) { 696 $( 'html, body' ).animate({ 697 scrollTop: sidebarBounds.top - 130 698 }, 200 ); 699 } 700 701 window.setTimeout( function() { 702 // Cannot use a callback in the animation above as it fires twice, 703 // have to queue this "by hand". 704 widget.find( '.widget-title' ).trigger('click'); 705 // At the end of the animation, announce the widget has been added. 706 window.wp.a11y.speak( wp.i18n.__( 'Widget has been added to the selected sidebar' ), 'assertive' ); 707 }, 250 ); 708 }, 709 710 closeChooser: function() { 711 var self = this, 712 widgetInQuestion = $( '#available-widgets .widget-in-question' ); 713 714 $( '.widgets-chooser' ).slideUp( 200, function() { 715 $( '#wpbody-content' ).append( this ); 716 self.clearWidgetSelection(); 717 // Move focus back to the toggle button. 718 widgetInQuestion.find( '.widget-action' ).attr( 'aria-expanded', 'false' ).focus(); 719 }); 720 }, 721 722 clearWidgetSelection: function() { 723 $( '#widgets-left' ).removeClass( 'chooser' ); 724 $( '.widget-in-question' ).removeClass( 'widget-in-question' ); 725 }, 726 727 /** 728 * Closes a Sidebar that was previously closed, but opened by dragging a Widget over it. 729 * 730 * Used when a Widget gets dragged in/out of the Sidebar and never dropped. 731 * 732 * @param {Object} event jQuery event object. 733 */ 734 closeSidebar: function( event ) { 735 this.hoveredSidebar 736 .addClass( 'closed' ) 737 .find( '.handlediv' ).attr( 'aria-expanded', 'false' ); 738 739 $( event.target ).css( 'min-height', '' ); 740 this.hoveredSidebar = null; 741 } 742 }; 743 744 $( function(){ wpWidgets.init(); } ); 745 746 })(jQuery); 747 748 /** 749 * Removed in 5.5.0, needed for back-compatibility. 750 * 751 * @since 4.9.0 752 * @deprecated 5.5.0 753 * 754 * @type {object} 755 */ 756 wpWidgets.l10n = wpWidgets.l10n || { 757 save: '', 758 saved: '', 759 saveAlert: '', 760 widgetAdded: '' 761 }; 762 763 wpWidgets.l10n = window.wp.deprecateL10nObject( 'wpWidgets.l10n', wpWidgets.l10n, '5.5.0' );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Nov 21 01:00:03 2024 | Cross-referenced by PHPXref 0.7.1 |