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


Generated: Wed Sep 18 01:00:03 2019 Cross-referenced by PHPXref 0.7.1