[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-admin/js/ -> widgets.js (source)

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


Generated: Sat Apr 4 01:00:03 2020 Cross-referenced by PHPXref 0.7.1