[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/ -> customize-loader.js (source)

   1  /**
   2   * @output wp-includes/js/customize-loader.js
   3   */
   4  
   5  /* global _wpCustomizeLoaderSettings */
   6  
   7  /**
   8   * Expose a public API that allows the customizer to be
   9   * loaded on any page.
  10   *
  11   * @namespace wp
  12   */
  13  window.wp = window.wp || {};
  14  
  15  (function( exports, $ ){
  16      var api = wp.customize,
  17          Loader;
  18  
  19      $.extend( $.support, {
  20          history: !! ( window.history && history.pushState ),
  21          hashchange: ('onhashchange' in window) && (document.documentMode === undefined || document.documentMode > 7)
  22      });
  23  
  24      /**
  25       * Allows the Customizer to be overlayed on any page.
  26       *
  27       * By default, any element in the body with the load-customize class will open
  28       * an iframe overlay with the URL specified.
  29       *
  30       *     e.g. <a class="load-customize" href="<?php echo wp_customize_url(); ?>">Open Customizer</a>
  31       *
  32       * @memberOf wp.customize
  33       *
  34       * @class
  35       * @augments wp.customize.Events
  36       */
  37      Loader = $.extend( {}, api.Events,/** @lends wp.customize.Loader.prototype */{
  38          /**
  39           * Setup the Loader; triggered on document#ready.
  40           */
  41          initialize: function() {
  42              this.body = $( document.body );
  43  
  44              // Ensure the loader is supported.
  45              // Check for settings, postMessage support, and whether we require CORS support.
  46              if ( ! Loader.settings || ! $.support.postMessage || ( ! $.support.cors && Loader.settings.isCrossDomain ) ) {
  47                  return;
  48              }
  49  
  50              this.window  = $( window );
  51              this.element = $( '<div id="customize-container" />' ).appendTo( this.body );
  52  
  53              // Bind events for opening and closing the overlay.
  54              this.bind( 'open', this.overlay.show );
  55              this.bind( 'close', this.overlay.hide );
  56  
  57              // Any element in the body with the `load-customize` class opens
  58              // the Customizer.
  59              $('#wpbody').on( 'click', '.load-customize', function( event ) {
  60                  event.preventDefault();
  61  
  62                  // Store a reference to the link that opened the Customizer.
  63                  Loader.link = $(this);
  64                  // Load the theme.
  65                  Loader.open( Loader.link.attr('href') );
  66              });
  67  
  68              // Add navigation listeners.
  69              if ( $.support.history ) {
  70                  this.window.on( 'popstate', Loader.popstate );
  71              }
  72  
  73              if ( $.support.hashchange ) {
  74                  this.window.on( 'hashchange', Loader.hashchange );
  75                  this.window.triggerHandler( 'hashchange' );
  76              }
  77          },
  78  
  79          popstate: function( e ) {
  80              var state = e.originalEvent.state;
  81              if ( state && state.customize ) {
  82                  Loader.open( state.customize );
  83              } else if ( Loader.active ) {
  84                  Loader.close();
  85              }
  86          },
  87  
  88          hashchange: function() {
  89              var hash = window.location.toString().split('#')[1];
  90  
  91              if ( hash && 0 === hash.indexOf( 'wp_customize=on' ) ) {
  92                  Loader.open( Loader.settings.url + '?' + hash );
  93              }
  94  
  95              if ( ! hash && ! $.support.history ) {
  96                  Loader.close();
  97              }
  98          },
  99  
 100          beforeunload: function () {
 101              if ( ! Loader.saved() ) {
 102                  return Loader.settings.l10n.saveAlert;
 103              }
 104          },
 105  
 106          /**
 107           * Open the Customizer overlay for a specific URL.
 108           *
 109           * @param string src URL to load in the Customizer.
 110           */
 111          open: function( src ) {
 112  
 113              if ( this.active ) {
 114                  return;
 115              }
 116  
 117              // Load the full page on mobile devices.
 118              if ( Loader.settings.browser.mobile ) {
 119                  return window.location = src;
 120              }
 121  
 122              // Store the document title prior to opening the Live Preview.
 123              this.originalDocumentTitle = document.title;
 124  
 125              this.active = true;
 126              this.body.addClass('customize-loading');
 127  
 128              /*
 129               * Track the dirtiness state (whether the drafted changes have been published)
 130               * of the Customizer in the iframe. This is used to decide whether to display
 131               * an AYS alert if the user tries to close the window before saving changes.
 132               */
 133              this.saved = new api.Value( true );
 134  
 135              this.iframe = $( '<iframe />', { 'src': src, 'title': Loader.settings.l10n.mainIframeTitle } ).appendTo( this.element );
 136              this.iframe.one( 'load', this.loaded );
 137  
 138              // Create a postMessage connection with the iframe.
 139              this.messenger = new api.Messenger({
 140                  url: src,
 141                  channel: 'loader',
 142                  targetWindow: this.iframe[0].contentWindow
 143              });
 144  
 145              // Expose the changeset UUID on the parent window's URL so that the customized state can survive a refresh.
 146              if ( history.replaceState ) {
 147                  this.messenger.bind( 'changeset-uuid', function( changesetUuid ) {
 148                      var urlParser = document.createElement( 'a' );
 149                      urlParser.href = location.href;
 150                      urlParser.search = $.param( _.extend(
 151                          api.utils.parseQueryString( urlParser.search.substr( 1 ) ),
 152                          { changeset_uuid: changesetUuid }
 153                      ) );
 154                      history.replaceState( { customize: urlParser.href }, '', urlParser.href );
 155                  } );
 156              }
 157  
 158              // Wait for the connection from the iframe before sending any postMessage events.
 159              this.messenger.bind( 'ready', function() {
 160                  Loader.messenger.send( 'back' );
 161              });
 162  
 163              this.messenger.bind( 'close', function() {
 164                  if ( $.support.history ) {
 165                      history.back();
 166                  } else if ( $.support.hashchange ) {
 167                      window.location.hash = '';
 168                  } else {
 169                      Loader.close();
 170                  }
 171              });
 172  
 173              // Prompt AYS dialog when navigating away.
 174              $( window ).on( 'beforeunload', this.beforeunload );
 175  
 176              this.messenger.bind( 'saved', function () {
 177                  Loader.saved( true );
 178              } );
 179              this.messenger.bind( 'change', function () {
 180                  Loader.saved( false );
 181              } );
 182  
 183              this.messenger.bind( 'title', function( newTitle ){
 184                  window.document.title = newTitle;
 185              });
 186  
 187              this.pushState( src );
 188  
 189              this.trigger( 'open' );
 190          },
 191  
 192          pushState: function ( src ) {
 193              var hash = src.split( '?' )[1];
 194  
 195              // Ensure we don't call pushState if the user hit the forward button.
 196              if ( $.support.history && window.location.href !== src ) {
 197                  history.pushState( { customize: src }, '', src );
 198              } else if ( ! $.support.history && $.support.hashchange && hash ) {
 199                  window.location.hash = 'wp_customize=on&' + hash;
 200              }
 201  
 202              this.trigger( 'open' );
 203          },
 204  
 205          /**
 206           * Callback after the Customizer has been opened.
 207           */
 208          opened: function() {
 209              Loader.body.addClass( 'customize-active full-overlay-active' ).attr( 'aria-busy', 'true' );
 210          },
 211  
 212          /**
 213           * Close the Customizer overlay.
 214           */
 215          close: function() {
 216              var self = this, onConfirmClose;
 217              if ( ! self.active ) {
 218                  return;
 219              }
 220  
 221              onConfirmClose = function( confirmed ) {
 222                  if ( confirmed ) {
 223                      self.active = false;
 224                      self.trigger( 'close' );
 225  
 226                      // Restore document title prior to opening the Live Preview.
 227                      if ( self.originalDocumentTitle ) {
 228                          document.title = self.originalDocumentTitle;
 229                      }
 230                  } else {
 231  
 232                      // Go forward since Customizer is exited by history.back().
 233                      history.forward();
 234                  }
 235                  self.messenger.unbind( 'confirmed-close', onConfirmClose );
 236              };
 237              self.messenger.bind( 'confirmed-close', onConfirmClose );
 238  
 239              Loader.messenger.send( 'confirm-close' );
 240          },
 241  
 242          /**
 243           * Callback after the Customizer has been closed.
 244           */
 245          closed: function() {
 246              Loader.iframe.remove();
 247              Loader.messenger.destroy();
 248              Loader.iframe    = null;
 249              Loader.messenger = null;
 250              Loader.saved     = null;
 251              Loader.body.removeClass( 'customize-active full-overlay-active' ).removeClass( 'customize-loading' );
 252              $( window ).off( 'beforeunload', Loader.beforeunload );
 253              /*
 254               * Return focus to the link that opened the Customizer overlay after
 255               * the body element visibility is restored.
 256               */
 257              if ( Loader.link ) {
 258                  Loader.link.focus();
 259              }
 260          },
 261  
 262          /**
 263           * Callback for the `load` event on the Customizer iframe.
 264           */
 265          loaded: function() {
 266              Loader.body.removeClass( 'customize-loading' ).attr( 'aria-busy', 'false' );
 267          },
 268  
 269          /**
 270           * Overlay hide/show utility methods.
 271           */
 272          overlay: {
 273              show: function() {
 274                  this.element.fadeIn( 200, Loader.opened );
 275              },
 276  
 277              hide: function() {
 278                  this.element.fadeOut( 200, Loader.closed );
 279              }
 280          }
 281      });
 282  
 283      // Bootstrap the Loader on document#ready.
 284      $( function() {
 285          Loader.settings = _wpCustomizeLoaderSettings;
 286          Loader.initialize();
 287      });
 288  
 289      // Expose the API publicly on window.wp.customize.Loader.
 290      api.Loader = Loader;
 291  })( wp, jQuery );


Generated : Mon Mar 18 08:20:01 2024 Cross-referenced by PHPXref