[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-admin/js/ -> site-icon.js (source)

   1  /**
   2   * Handle the site icon setting in options-general.php.
   3   *
   4   * @since 6.5.0
   5   * @output wp-admin/js/site-icon.js
   6   */
   7  
   8  /* global jQuery, wp */
   9  
  10  ( function ( $ ) {
  11      var $chooseButton = $( '#choose-from-library-button' ),
  12          $iconPreview = $( '#site-icon-preview' ),
  13          $browserIconPreview = $( '#browser-icon-preview' ),
  14          $appIconPreview = $( '#app-icon-preview' ),
  15          $hiddenDataField = $( '#site_icon_hidden_field' ),
  16          $removeButton = $( '#js-remove-site-icon' ),
  17          $adminBarSiteName = $( '#wp-admin-bar-site-name' ),
  18          $adminBarSiteNameLink = $adminBarSiteName.children( 'a' ).first(),
  19          frame;
  20  
  21      /**
  22       * Calculate image selection options based on the attachment dimensions.
  23       *
  24       * @since 6.5.0
  25       *
  26       * @param {Object} attachment The attachment object representing the image.
  27       * @return {Object} The image selection options.
  28       */
  29  	function calculateImageSelectOptions( attachment ) {
  30          var realWidth = attachment.get( 'width' ),
  31              realHeight = attachment.get( 'height' ),
  32              xInit = 512,
  33              yInit = 512,
  34              ratio = xInit / yInit,
  35              xImg = xInit,
  36              yImg = yInit,
  37              x1,
  38              y1,
  39              imgSelectOptions;
  40  
  41          if ( realWidth / realHeight > ratio ) {
  42              yInit = realHeight;
  43              xInit = yInit * ratio;
  44          } else {
  45              xInit = realWidth;
  46              yInit = xInit / ratio;
  47          }
  48  
  49          x1 = ( realWidth - xInit ) / 2;
  50          y1 = ( realHeight - yInit ) / 2;
  51  
  52          imgSelectOptions = {
  53              aspectRatio: xInit + ':' + yInit,
  54              handles: true,
  55              keys: true,
  56              instance: true,
  57              persistent: true,
  58              imageWidth: realWidth,
  59              imageHeight: realHeight,
  60              minWidth: xImg > xInit ? xInit : xImg,
  61              minHeight: yImg > yInit ? yInit : yImg,
  62              x1: x1,
  63              y1: y1,
  64              x2: xInit + x1,
  65              y2: yInit + y1,
  66          };
  67  
  68          return imgSelectOptions;
  69      }
  70  
  71      /**
  72       * Initializes the media frame for selecting or cropping an image.
  73       *
  74       * @since 6.5.0
  75       */
  76      $chooseButton.on( 'click', function () {
  77          var $el = $( this );
  78  
  79          // Create the media frame.
  80          frame = wp.media( {
  81              button: {
  82                  // Set the text of the button.
  83                  text: $el.data( 'update' ),
  84  
  85                  // Don't close, we might need to crop.
  86                  close: false,
  87              },
  88              states: [
  89                  new wp.media.controller.Library( {
  90                      title: $el.data( 'choose-text' ),
  91                      library: wp.media.query( { type: 'image' } ),
  92                      date: false,
  93                      suggestedWidth: $el.data( 'size' ),
  94                      suggestedHeight: $el.data( 'size' ),
  95                  } ),
  96                  new wp.media.controller.SiteIconCropper( {
  97                      control: {
  98                          params: {
  99                              width: $el.data( 'size' ),
 100                              height: $el.data( 'size' ),
 101                          },
 102                      },
 103                      imgSelectOptions: calculateImageSelectOptions,
 104                  } ),
 105              ],
 106          } );
 107  
 108          frame.on( 'cropped', function ( attachment ) {
 109              $hiddenDataField.val( attachment.id );
 110              switchToUpdate( attachment );
 111              frame.close();
 112  
 113              // Start over with a frame that is so fresh and so clean clean.
 114              frame = null;
 115          } );
 116  
 117          // When an image is selected, run a callback.
 118          frame.on( 'select', function () {
 119              // Grab the selected attachment.
 120              var attachment = frame.state().get( 'selection' ).first();
 121  
 122              if (
 123                  attachment.attributes.height === $el.data( 'size' ) &&
 124                  $el.data( 'size' ) === attachment.attributes.width
 125              ) {
 126                  switchToUpdate( attachment.attributes );
 127                  frame.close();
 128  
 129                  // Set the value of the hidden input to the attachment id.
 130                  $hiddenDataField.val( attachment.id );
 131              } else {
 132                  frame.setState( 'cropper' );
 133              }
 134          } );
 135  
 136          frame.open();
 137      } );
 138  
 139      /**
 140       * Update the UI when a site icon is selected.
 141       *
 142       * @since 6.5.0
 143       *
 144       * @param {array} attributes The attributes for the attachment.
 145       */
 146  	function switchToUpdate( attributes ) {
 147          var i18nAppAlternativeString, i18nBrowserAlternativeString;
 148  
 149          if ( attributes.alt ) {
 150              i18nAppAlternativeString = wp.i18n.sprintf(
 151                  /* translators: %s: The selected image alt text. */
 152                  wp.i18n.__( 'App icon preview: Current image: %s' ),
 153                  attributes.alt
 154              );
 155              i18nBrowserAlternativeString = wp.i18n.sprintf(
 156                  /* translators: %s: The selected image alt text. */
 157                  wp.i18n.__( 'Browser icon preview: Current image: %s' ),
 158                  attributes.alt
 159              );
 160          } else {
 161              i18nAppAlternativeString = wp.i18n.sprintf(
 162                  /* translators: %s: The selected image filename. */
 163                  wp.i18n.__(
 164                      'App icon preview: The current image has no alternative text. The file name is: %s'
 165                  ),
 166                  attributes.filename
 167              );
 168              i18nBrowserAlternativeString = wp.i18n.sprintf(
 169                  /* translators: %s: The selected image filename. */
 170                  wp.i18n.__(
 171                      'Browser icon preview: The current image has no alternative text. The file name is: %s'
 172                  ),
 173                  attributes.filename
 174              );
 175          }
 176  
 177          // Set site-icon-img src and alternative text to app icon preview.
 178          $appIconPreview.attr( {
 179              src: attributes.url,
 180              alt: i18nAppAlternativeString,
 181          } );
 182  
 183          // Set site-icon-img src and alternative text to browser preview.
 184          $browserIconPreview.attr( {
 185              src: attributes.url,
 186              alt: i18nBrowserAlternativeString,
 187          } );
 188  
 189          // Remove hidden class from icon preview div and remove button.
 190          $iconPreview.removeClass( 'hidden' );
 191          $removeButton.removeClass( 'hidden' );
 192  
 193          // Set the global CSS variable for --site-icon-url to the selected image URL.
 194          document.documentElement.style.setProperty(
 195              '--site-icon-url',
 196              'url(' + attributes.url + ')'
 197          );
 198  
 199          // Replace the site icon in the admin bar.
 200          $adminBarSiteNameLink.children( 'img.site-icon' ).remove();
 201          $( '<img />' )
 202              .attr( {
 203                  class: 'site-icon',
 204                  src: attributes.url,
 205                  alt: '',
 206                  width: 20,
 207                  height: 20,
 208              } )
 209              .prependTo( $adminBarSiteNameLink );
 210          $adminBarSiteName.addClass( 'has-site-icon' );
 211  
 212          // If the choose button is not in the update state, swap the classes.
 213          if ( $chooseButton.attr( 'data-state' ) !== '1' ) {
 214              $chooseButton.attr( {
 215                  class: $chooseButton.attr( 'data-alt-classes' ),
 216                  'data-alt-classes': $chooseButton.attr( 'class' ),
 217                  'data-state': '1',
 218              } );
 219          }
 220  
 221          // Swap the text of the choose button.
 222          $chooseButton.text( $chooseButton.attr( 'data-update-text' ) );
 223      }
 224  
 225      /**
 226       * Handles the click event of the remove button.
 227       *
 228       * @since 6.5.0
 229       */
 230      $removeButton.on( 'click', function () {
 231          $hiddenDataField.val( 'false' );
 232          $( this ).toggleClass( 'hidden' );
 233          $iconPreview.toggleClass( 'hidden' );
 234          $browserIconPreview.attr( {
 235              src: '',
 236              alt: '',
 237          } );
 238          $appIconPreview.attr( {
 239              src: '',
 240              alt: '',
 241          } );
 242  
 243          // Remove the site icon from the admin bar.
 244          $adminBarSiteNameLink.children( 'img.site-icon' ).remove();
 245          $adminBarSiteName.removeClass( 'has-site-icon' );
 246  
 247          /**
 248           * Resets state to the button, for correct visual style and state.
 249           * Updates the text of the button.
 250           * Sets focus state to the button.
 251           */
 252          $chooseButton
 253              .attr( {
 254                  class: $chooseButton.attr( 'data-alt-classes' ),
 255                  'data-alt-classes': $chooseButton.attr( 'class' ),
 256                  'data-state': '',
 257              } )
 258              .text( $chooseButton.attr( 'data-choose-text' ) )
 259              .trigger( 'focus' );
 260      } );
 261  } )( jQuery );


Generated : Fri Jul 24 08:20:19 2026 Cross-referenced by PHPXref