[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

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

   1  /**
   2   * @output wp-includes/js/customize-base.js
   3   */
   4  
   5  /** @namespace wp */
   6  window.wp = window.wp || {};
   7  
   8  (function( exports, $ ){
   9      var api = {}, ctor, inherits,
  10          slice = Array.prototype.slice;
  11  
  12      // Shared empty constructor function to aid in prototype-chain creation.
  13      ctor = function() {};
  14  
  15      /**
  16       * Helper function to correctly set up the prototype chain, for subclasses.
  17       * Similar to `goog.inherits`, but uses a hash of prototype properties and
  18       * class properties to be extended.
  19       *
  20       * @param  object parent      Parent class constructor to inherit from.
  21       * @param  object protoProps  Properties to apply to the prototype for use as class instance properties.
  22       * @param  object staticProps Properties to apply directly to the class constructor.
  23       * @return child              The subclassed constructor.
  24       */
  25      inherits = function( parent, protoProps, staticProps ) {
  26          var child;
  27  
  28          // The constructor function for the new subclass is either defined by you
  29          // (the "constructor" property in your `extend` definition), or defaulted
  30          // by us to simply call `super()`.
  31          if ( protoProps && protoProps.hasOwnProperty( 'constructor' ) ) {
  32              child = protoProps.constructor;
  33          } else {
  34              child = function() {
  35                  // Storing the result `super()` before returning the value
  36                  // prevents a bug in Opera where, if the constructor returns
  37                  // a function, Opera will reject the return value in favor of
  38                  // the original object. This causes all sorts of trouble.
  39                  var result = parent.apply( this, arguments );
  40                  return result;
  41              };
  42          }
  43  
  44          // Inherit class (static) properties from parent.
  45          $.extend( child, parent );
  46  
  47          // Set the prototype chain to inherit from `parent`, without calling
  48          // `parent`'s constructor function.
  49          ctor.prototype  = parent.prototype;
  50          child.prototype = new ctor();
  51  
  52          // Add prototype properties (instance properties) to the subclass,
  53          // if supplied.
  54          if ( protoProps )
  55              $.extend( child.prototype, protoProps );
  56  
  57          // Add static properties to the constructor function, if supplied.
  58          if ( staticProps )
  59              $.extend( child, staticProps );
  60  
  61          // Correctly set child's `prototype.constructor`.
  62          child.prototype.constructor = child;
  63  
  64          // Set a convenience property in case the parent's prototype is needed later.
  65          child.__super__ = parent.prototype;
  66  
  67          return child;
  68      };
  69  
  70      /**
  71       * Base class for object inheritance.
  72       */
  73      api.Class = function( applicator, argsArray, options ) {
  74          var magic, args = arguments;
  75  
  76          if ( applicator && argsArray && api.Class.applicator === applicator ) {
  77              args = argsArray;
  78              $.extend( this, options || {} );
  79          }
  80  
  81          magic = this;
  82  
  83          /*
  84           * If the class has a method called "instance",
  85           * the return value from the class' constructor will be a function that
  86           * calls the "instance" method.
  87           *
  88           * It is also an object that has properties and methods inside it.
  89           */
  90          if ( this.instance ) {
  91              magic = function() {
  92                  return magic.instance.apply( magic, arguments );
  93              };
  94  
  95              $.extend( magic, this );
  96          }
  97  
  98          magic.initialize.apply( magic, args );
  99          return magic;
 100      };
 101  
 102      /**
 103       * Creates a subclass of the class.
 104       *
 105       * @param  object protoProps  Properties to apply to the prototype.
 106       * @param  object staticProps Properties to apply directly to the class.
 107       * @return child              The subclass.
 108       */
 109      api.Class.extend = function( protoProps, classProps ) {
 110          var child = inherits( this, protoProps, classProps );
 111          child.extend = this.extend;
 112          return child;
 113      };
 114  
 115      api.Class.applicator = {};
 116  
 117      /**
 118       * Initialize a class instance.
 119       *
 120       * Override this function in a subclass as needed.
 121       */
 122      api.Class.prototype.initialize = function() {};
 123  
 124      /*
 125       * Checks whether a given instance extended a constructor.
 126       *
 127       * The magic surrounding the instance parameter causes the instanceof
 128       * keyword to return inaccurate results; it defaults to the function's
 129       * prototype instead of the constructor chain. Hence this function.
 130       */
 131      api.Class.prototype.extended = function( constructor ) {
 132          var proto = this;
 133  
 134          while ( typeof proto.constructor !== 'undefined' ) {
 135              if ( proto.constructor === constructor )
 136                  return true;
 137              if ( typeof proto.constructor.__super__ === 'undefined' )
 138                  return false;
 139              proto = proto.constructor.__super__;
 140          }
 141          return false;
 142      };
 143  
 144      /**
 145       * An events manager object, offering the ability to bind to and trigger events.
 146       *
 147       * Used as a mixin.
 148       */
 149      api.Events = {
 150          trigger: function( id ) {
 151              if ( this.topics && this.topics[ id ] )
 152                  this.topics[ id ].fireWith( this, slice.call( arguments, 1 ) );
 153              return this;
 154          },
 155  
 156          bind: function( id ) {
 157              this.topics = this.topics || {};
 158              this.topics[ id ] = this.topics[ id ] || $.Callbacks();
 159              this.topics[ id ].add.apply( this.topics[ id ], slice.call( arguments, 1 ) );
 160              return this;
 161          },
 162  
 163          unbind: function( id ) {
 164              if ( this.topics && this.topics[ id ] )
 165                  this.topics[ id ].remove.apply( this.topics[ id ], slice.call( arguments, 1 ) );
 166              return this;
 167          }
 168      };
 169  
 170      /**
 171       * Observable values that support two-way binding.
 172       *
 173       * @memberOf wp.customize
 174       * @alias wp.customize.Value
 175       *
 176       * @constructor
 177       */
 178      api.Value = api.Class.extend(/** @lends wp.customize.Value.prototype */{
 179          /**
 180           * @param {mixed}  initial The initial value.
 181           * @param {object} options
 182           */
 183          initialize: function( initial, options ) {
 184              this._value = initial; // @todo: potentially change this to a this.set() call.
 185              this.callbacks = $.Callbacks();
 186              this._dirty = false;
 187  
 188              $.extend( this, options || {} );
 189  
 190              this.set = $.proxy( this.set, this );
 191          },
 192  
 193          /*
 194           * Magic. Returns a function that will become the instance.
 195           * Set to null to prevent the instance from extending a function.
 196           */
 197          instance: function() {
 198              return arguments.length ? this.set.apply( this, arguments ) : this.get();
 199          },
 200  
 201          /**
 202           * Get the value.
 203           *
 204           * @return {mixed}
 205           */
 206          get: function() {
 207              return this._value;
 208          },
 209  
 210          /**
 211           * Set the value and trigger all bound callbacks.
 212           *
 213           * @param {object} to New value.
 214           */
 215          set: function( to ) {
 216              var from = this._value;
 217  
 218              to = this._setter.apply( this, arguments );
 219              to = this.validate( to );
 220  
 221              // Bail if the sanitized value is null or unchanged.
 222              if ( null === to || _.isEqual( from, to ) ) {
 223                  return this;
 224              }
 225  
 226              this._value = to;
 227              this._dirty = true;
 228  
 229              this.callbacks.fireWith( this, [ to, from ] );
 230  
 231              return this;
 232          },
 233  
 234          _setter: function( to ) {
 235              return to;
 236          },
 237  
 238          setter: function( callback ) {
 239              var from = this.get();
 240              this._setter = callback;
 241              // Temporarily clear value so setter can decide if it's valid.
 242              this._value = null;
 243              this.set( from );
 244              return this;
 245          },
 246  
 247          resetSetter: function() {
 248              this._setter = this.constructor.prototype._setter;
 249              this.set( this.get() );
 250              return this;
 251          },
 252  
 253          validate: function( value ) {
 254              return value;
 255          },
 256  
 257          /**
 258           * Bind a function to be invoked whenever the value changes.
 259           *
 260           * @param {...Function} A function, or multiple functions, to add to the callback stack.
 261           */
 262          bind: function() {
 263              this.callbacks.add.apply( this.callbacks, arguments );
 264              return this;
 265          },
 266  
 267          /**
 268           * Unbind a previously bound function.
 269           *
 270           * @param {...Function} A function, or multiple functions, to remove from the callback stack.
 271           */
 272          unbind: function() {
 273              this.callbacks.remove.apply( this.callbacks, arguments );
 274              return this;
 275          },
 276  
 277          link: function() { // values*
 278              var set = this.set;
 279              $.each( arguments, function() {
 280                  this.bind( set );
 281              });
 282              return this;
 283          },
 284  
 285          unlink: function() { // values*
 286              var set = this.set;
 287              $.each( arguments, function() {
 288                  this.unbind( set );
 289              });
 290              return this;
 291          },
 292  
 293          sync: function() { // values*
 294              var that = this;
 295              $.each( arguments, function() {
 296                  that.link( this );
 297                  this.link( that );
 298              });
 299              return this;
 300          },
 301  
 302          unsync: function() { // values*
 303              var that = this;
 304              $.each( arguments, function() {
 305                  that.unlink( this );
 306                  this.unlink( that );
 307              });
 308              return this;
 309          }
 310      });
 311  
 312      /**
 313       * A collection of observable values.
 314       *
 315       * @memberOf wp.customize
 316       * @alias wp.customize.Values
 317       *
 318       * @constructor
 319       * @augments wp.customize.Class
 320       * @mixes wp.customize.Events
 321       */
 322      api.Values = api.Class.extend(/** @lends wp.customize.Values.prototype */{
 323  
 324          /**
 325           * The default constructor for items of the collection.
 326           *
 327           * @type {object}
 328           */
 329          defaultConstructor: api.Value,
 330  
 331          initialize: function( options ) {
 332              $.extend( this, options || {} );
 333  
 334              this._value = {};
 335              this._deferreds = {};
 336          },
 337  
 338          /**
 339           * Get the instance of an item from the collection if only ID is specified.
 340           *
 341           * If more than one argument is supplied, all are expected to be IDs and
 342           * the last to be a function callback that will be invoked when the requested
 343           * items are available.
 344           *
 345           * @see {api.Values.when}
 346           *
 347           * @param  {string}   id ID of the item.
 348           * @param  {...}         Zero or more IDs of items to wait for and a callback
 349           *                       function to invoke when they're available. Optional.
 350           * @return {mixed}    The item instance if only one ID was supplied.
 351           *                    A Deferred Promise object if a callback function is supplied.
 352           */
 353          instance: function( id ) {
 354              if ( arguments.length === 1 )
 355                  return this.value( id );
 356  
 357              return this.when.apply( this, arguments );
 358          },
 359  
 360          /**
 361           * Get the instance of an item.
 362           *
 363           * @param  {string} id The ID of the item.
 364           * @return {[type]}    [description]
 365           */
 366          value: function( id ) {
 367              return this._value[ id ];
 368          },
 369  
 370          /**
 371           * Whether the collection has an item with the given ID.
 372           *
 373           * @param  {string}  id The ID of the item to look for.
 374           * @return {Boolean}
 375           */
 376          has: function( id ) {
 377              return typeof this._value[ id ] !== 'undefined';
 378          },
 379  
 380          /**
 381           * Add an item to the collection.
 382           *
 383           * @param {string|wp.customize.Class} item - The item instance to add, or the ID for the instance to add. When an ID string is supplied, then itemObject must be provided.
 384           * @param {wp.customize.Class}        [itemObject] - The item instance when the first argument is a ID string.
 385           * @return {wp.customize.Class} The new item's instance, or an existing instance if already added.
 386           */
 387          add: function( item, itemObject ) {
 388              var collection = this, id, instance;
 389              if ( 'string' === typeof item ) {
 390                  id = item;
 391                  instance = itemObject;
 392              } else {
 393                  if ( 'string' !== typeof item.id ) {
 394                      throw new Error( 'Unknown key' );
 395                  }
 396                  id = item.id;
 397                  instance = item;
 398              }
 399  
 400              if ( collection.has( id ) ) {
 401                  return collection.value( id );
 402              }
 403  
 404              collection._value[ id ] = instance;
 405              instance.parent = collection;
 406  
 407              // Propagate a 'change' event on an item up to the collection.
 408              if ( instance.extended( api.Value ) ) {
 409                  instance.bind( collection._change );
 410              }
 411  
 412              collection.trigger( 'add', instance );
 413  
 414              // If a deferred object exists for this item,
 415              // resolve it.
 416              if ( collection._deferreds[ id ] ) {
 417                  collection._deferreds[ id ].resolve();
 418              }
 419  
 420              return collection._value[ id ];
 421          },
 422  
 423          /**
 424           * Create a new item of the collection using the collection's default constructor
 425           * and store it in the collection.
 426           *
 427           * @param  {string} id    The ID of the item.
 428           * @param  {mixed}  value Any extra arguments are passed into the item's initialize method.
 429           * @return {mixed}  The new item's instance.
 430           */
 431          create: function( id ) {
 432              return this.add( id, new this.defaultConstructor( api.Class.applicator, slice.call( arguments, 1 ) ) );
 433          },
 434  
 435          /**
 436           * Iterate over all items in the collection invoking the provided callback.
 437           *
 438           * @param  {Function} callback Function to invoke.
 439           * @param  {object}   context  Object context to invoke the function with. Optional.
 440           */
 441          each: function( callback, context ) {
 442              context = typeof context === 'undefined' ? this : context;
 443  
 444              $.each( this._value, function( key, obj ) {
 445                  callback.call( context, obj, key );
 446              });
 447          },
 448  
 449          /**
 450           * Remove an item from the collection.
 451           *
 452           * @param  {string} id The ID of the item to remove.
 453           */
 454          remove: function( id ) {
 455              var value = this.value( id );
 456  
 457              if ( value ) {
 458  
 459                  // Trigger event right before the element is removed from the collection.
 460                  this.trigger( 'remove', value );
 461  
 462                  if ( value.extended( api.Value ) ) {
 463                      value.unbind( this._change );
 464                  }
 465                  delete value.parent;
 466              }
 467  
 468              delete this._value[ id ];
 469              delete this._deferreds[ id ];
 470  
 471              // Trigger removed event after the item has been eliminated from the collection.
 472              if ( value ) {
 473                  this.trigger( 'removed', value );
 474              }
 475          },
 476  
 477          /**
 478           * Runs a callback once all requested values exist.
 479           *
 480           * when( ids*, [callback] );
 481           *
 482           * For example:
 483           *     when( id1, id2, id3, function( value1, value2, value3 ) {} );
 484           *
 485           * @returns $.Deferred.promise();
 486           */
 487          when: function() {
 488              var self = this,
 489                  ids  = slice.call( arguments ),
 490                  dfd  = $.Deferred();
 491  
 492              // If the last argument is a callback, bind it to .done()
 493              if ( $.isFunction( ids[ ids.length - 1 ] ) )
 494                  dfd.done( ids.pop() );
 495  
 496              /*
 497               * Create a stack of deferred objects for each item that is not
 498               * yet available, and invoke the supplied callback when they are.
 499               */
 500              $.when.apply( $, $.map( ids, function( id ) {
 501                  if ( self.has( id ) )
 502                      return;
 503  
 504                  /*
 505                   * The requested item is not available yet, create a deferred
 506                   * object to resolve when it becomes available.
 507                   */
 508                  return self._deferreds[ id ] = self._deferreds[ id ] || $.Deferred();
 509              })).done( function() {
 510                  var values = $.map( ids, function( id ) {
 511                          return self( id );
 512                      });
 513  
 514                  // If a value is missing, we've used at least one expired deferred.
 515                  // Call Values.when again to generate a new deferred.
 516                  if ( values.length !== ids.length ) {
 517                      // ids.push( callback );
 518                      self.when.apply( self, ids ).done( function() {
 519                          dfd.resolveWith( self, values );
 520                      });
 521                      return;
 522                  }
 523  
 524                  dfd.resolveWith( self, values );
 525              });
 526  
 527              return dfd.promise();
 528          },
 529  
 530          /**
 531           * A helper function to propagate a 'change' event from an item
 532           * to the collection itself.
 533           */
 534          _change: function() {
 535              this.parent.trigger( 'change', this );
 536          }
 537      });
 538  
 539      // Create a global events bus on the Customizer.
 540      $.extend( api.Values.prototype, api.Events );
 541  
 542  
 543      /**
 544       * Cast a string to a jQuery collection if it isn't already.
 545       *
 546       * @param {string|jQuery collection} element
 547       */
 548      api.ensure = function( element ) {
 549          return typeof element == 'string' ? $( element ) : element;
 550      };
 551  
 552      /**
 553       * An observable value that syncs with an element.
 554       *
 555       * Handles inputs, selects, and textareas by default.
 556       *
 557       * @memberOf wp.customize
 558       * @alias wp.customize.Element
 559       *
 560       * @constructor
 561       * @augments wp.customize.Value
 562       * @augments wp.customize.Class
 563       */
 564      api.Element = api.Value.extend(/** @lends wp.customize.Element */{
 565          initialize: function( element, options ) {
 566              var self = this,
 567                  synchronizer = api.Element.synchronizer.html,
 568                  type, update, refresh;
 569  
 570              this.element = api.ensure( element );
 571              this.events = '';
 572  
 573              if ( this.element.is( 'input, select, textarea' ) ) {
 574                  type = this.element.prop( 'type' );
 575                  this.events += ' change input';
 576                  synchronizer = api.Element.synchronizer.val;
 577  
 578                  if ( this.element.is( 'input' ) && api.Element.synchronizer[ type ] ) {
 579                      synchronizer = api.Element.synchronizer[ type ];
 580                  }
 581              }
 582  
 583              api.Value.prototype.initialize.call( this, null, $.extend( options || {}, synchronizer ) );
 584              this._value = this.get();
 585  
 586              update = this.update;
 587              refresh = this.refresh;
 588  
 589              this.update = function( to ) {
 590                  if ( to !== refresh.call( self ) ) {
 591                      update.apply( this, arguments );
 592                  }
 593              };
 594              this.refresh = function() {
 595                  self.set( refresh.call( self ) );
 596              };
 597  
 598              this.bind( this.update );
 599              this.element.bind( this.events, this.refresh );
 600          },
 601  
 602          find: function( selector ) {
 603              return $( selector, this.element );
 604          },
 605  
 606          refresh: function() {},
 607  
 608          update: function() {}
 609      });
 610  
 611      api.Element.synchronizer = {};
 612  
 613      $.each( [ 'html', 'val' ], function( index, method ) {
 614          api.Element.synchronizer[ method ] = {
 615              update: function( to ) {
 616                  this.element[ method ]( to );
 617              },
 618              refresh: function() {
 619                  return this.element[ method ]();
 620              }
 621          };
 622      });
 623  
 624      api.Element.synchronizer.checkbox = {
 625          update: function( to ) {
 626              this.element.prop( 'checked', to );
 627          },
 628          refresh: function() {
 629              return this.element.prop( 'checked' );
 630          }
 631      };
 632  
 633      api.Element.synchronizer.radio = {
 634          update: function( to ) {
 635              this.element.filter( function() {
 636                  return this.value === to;
 637              }).prop( 'checked', true );
 638          },
 639          refresh: function() {
 640              return this.element.filter( ':checked' ).val();
 641          }
 642      };
 643  
 644      $.support.postMessage = !! window.postMessage;
 645  
 646      /**
 647       * A communicator for sending data from one window to another over postMessage.
 648       *
 649       * @memberOf wp.customize
 650       * @alias wp.customize.Messenger
 651       *
 652       * @constructor
 653       * @augments wp.customize.Class
 654       * @mixes wp.customize.Events
 655       */
 656      api.Messenger = api.Class.extend(/** @lends wp.customize.Messenger.prototype */{
 657          /**
 658           * Create a new Value.
 659           *
 660           * @param  {string} key     Unique identifier.
 661           * @param  {mixed}  initial Initial value.
 662           * @param  {mixed}  options Options hash. Optional.
 663           * @return {Value}          Class instance of the Value.
 664           */
 665          add: function( key, initial, options ) {
 666              return this[ key ] = new api.Value( initial, options );
 667          },
 668  
 669          /**
 670           * Initialize Messenger.
 671           *
 672           * @param  {object} params - Parameters to configure the messenger.
 673           *         {string} params.url - The URL to communicate with.
 674           *         {window} params.targetWindow - The window instance to communicate with. Default window.parent.
 675           *         {string} params.channel - If provided, will send the channel with each message and only accept messages a matching channel.
 676           * @param  {object} options - Extend any instance parameter or method with this object.
 677           */
 678          initialize: function( params, options ) {
 679              // Target the parent frame by default, but only if a parent frame exists.
 680              var defaultTarget = window.parent === window ? null : window.parent;
 681  
 682              $.extend( this, options || {} );
 683  
 684              this.add( 'channel', params.channel );
 685              this.add( 'url', params.url || '' );
 686              this.add( 'origin', this.url() ).link( this.url ).setter( function( to ) {
 687                  var urlParser = document.createElement( 'a' );
 688                  urlParser.href = to;
 689                  // Port stripping needed by IE since it adds to host but not to event.origin.
 690                  return urlParser.protocol + '//' + urlParser.host.replace( /:(80|443)$/, '' );
 691              });
 692  
 693              // first add with no value
 694              this.add( 'targetWindow', null );
 695              // This avoids SecurityErrors when setting a window object in x-origin iframe'd scenarios.
 696              this.targetWindow.set = function( to ) {
 697                  var from = this._value;
 698  
 699                  to = this._setter.apply( this, arguments );
 700                  to = this.validate( to );
 701  
 702                  if ( null === to || from === to ) {
 703                      return this;
 704                  }
 705  
 706                  this._value = to;
 707                  this._dirty = true;
 708  
 709                  this.callbacks.fireWith( this, [ to, from ] );
 710  
 711                  return this;
 712              };
 713              // now set it
 714              this.targetWindow( params.targetWindow || defaultTarget );
 715  
 716  
 717              // Since we want jQuery to treat the receive function as unique
 718              // to this instance, we give the function a new guid.
 719              //
 720              // This will prevent every Messenger's receive function from being
 721              // unbound when calling $.off( 'message', this.receive );
 722              this.receive = $.proxy( this.receive, this );
 723              this.receive.guid = $.guid++;
 724  
 725              $( window ).on( 'message', this.receive );
 726          },
 727  
 728          destroy: function() {
 729              $( window ).off( 'message', this.receive );
 730          },
 731  
 732          /**
 733           * Receive data from the other window.
 734           *
 735           * @param  {jQuery.Event} event Event with embedded data.
 736           */
 737          receive: function( event ) {
 738              var message;
 739  
 740              event = event.originalEvent;
 741  
 742              if ( ! this.targetWindow || ! this.targetWindow() ) {
 743                  return;
 744              }
 745  
 746              // Check to make sure the origin is valid.
 747              if ( this.origin() && event.origin !== this.origin() )
 748                  return;
 749  
 750              // Ensure we have a string that's JSON.parse-able
 751              if ( typeof event.data !== 'string' || event.data[0] !== '{' ) {
 752                  return;
 753              }
 754  
 755              message = JSON.parse( event.data );
 756  
 757              // Check required message properties.
 758              if ( ! message || ! message.id || typeof message.data === 'undefined' )
 759                  return;
 760  
 761              // Check if channel names match.
 762              if ( ( message.channel || this.channel() ) && this.channel() !== message.channel )
 763                  return;
 764  
 765              this.trigger( message.id, message.data );
 766          },
 767  
 768          /**
 769           * Send data to the other window.
 770           *
 771           * @param  {string} id   The event name.
 772           * @param  {object} data Data.
 773           */
 774          send: function( id, data ) {
 775              var message;
 776  
 777              data = typeof data === 'undefined' ? null : data;
 778  
 779              if ( ! this.url() || ! this.targetWindow() )
 780                  return;
 781  
 782              message = { id: id, data: data };
 783              if ( this.channel() )
 784                  message.channel = this.channel();
 785  
 786              this.targetWindow().postMessage( JSON.stringify( message ), this.origin() );
 787          }
 788      });
 789  
 790      // Add the Events mixin to api.Messenger.
 791      $.extend( api.Messenger.prototype, api.Events );
 792  
 793      /**
 794       * Notification.
 795       *
 796       * @class
 797       * @augments wp.customize.Class
 798       * @since 4.6.0
 799       *
 800       * @memberOf wp.customize
 801       * @alias wp.customize.Notification
 802       *
 803       * @param {string}  code - The error code.
 804       * @param {object}  params - Params.
 805       * @param {string}  params.message=null - The error message.
 806       * @param {string}  [params.type=error] - The notification type.
 807       * @param {boolean} [params.fromServer=false] - Whether the notification was server-sent.
 808       * @param {string}  [params.setting=null] - The setting ID that the notification is related to.
 809       * @param {*}       [params.data=null] - Any additional data.
 810       */
 811      api.Notification = api.Class.extend(/** @lends wp.customize.Notification.prototype */{
 812  
 813          /**
 814           * Template function for rendering the notification.
 815           *
 816           * This will be populated with template option or else it will be populated with template from the ID.
 817           *
 818           * @since 4.9.0
 819           * @var {Function}
 820           */
 821          template: null,
 822  
 823          /**
 824           * ID for the template to render the notification.
 825           *
 826           * @since 4.9.0
 827           * @var {string}
 828           */
 829          templateId: 'customize-notification',
 830  
 831          /**
 832           * Additional class names to add to the notification container.
 833           *
 834           * @since 4.9.0
 835           * @var {string}
 836           */
 837          containerClasses: '',
 838  
 839          /**
 840           * Initialize notification.
 841           *
 842           * @since 4.9.0
 843           *
 844           * @param {string}   code - Notification code.
 845           * @param {object}   params - Notification parameters.
 846           * @param {string}   params.message - Message.
 847           * @param {string}   [params.type=error] - Type.
 848           * @param {string}   [params.setting] - Related setting ID.
 849           * @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId.
 850           * @param {string}   [params.templateId] - ID for template to render the notification.
 851           * @param {string}   [params.containerClasses] - Additional class names to add to the notification container.
 852           * @param {boolean}  [params.dismissible] - Whether the notification can be dismissed.
 853           */
 854          initialize: function( code, params ) {
 855              var _params;
 856              this.code = code;
 857              _params = _.extend(
 858                  {
 859                      message: null,
 860                      type: 'error',
 861                      fromServer: false,
 862                      data: null,
 863                      setting: null,
 864                      template: null,
 865                      dismissible: false,
 866                      containerClasses: ''
 867                  },
 868                  params
 869              );
 870              delete _params.code;
 871              _.extend( this, _params );
 872          },
 873  
 874          /**
 875           * Render the notification.
 876           *
 877           * @since 4.9.0
 878           *
 879           * @returns {jQuery} Notification container element.
 880           */
 881          render: function() {
 882              var notification = this, container, data;
 883              if ( ! notification.template ) {
 884                  notification.template = wp.template( notification.templateId );
 885              }
 886              data = _.extend( {}, notification, {
 887                  alt: notification.parent && notification.parent.alt
 888              } );
 889              container = $( notification.template( data ) );
 890  
 891              if ( notification.dismissible ) {
 892                  container.find( '.notice-dismiss' ).on( 'click keydown', function( event ) {
 893                      if ( 'keydown' === event.type && 13 !== event.which ) {
 894                          return;
 895                      }
 896  
 897                      if ( notification.parent ) {
 898                          notification.parent.remove( notification.code );
 899                      } else {
 900                          container.remove();
 901                      }
 902                  });
 903              }
 904  
 905              return container;
 906          }
 907      });
 908  
 909      // The main API object is also a collection of all customizer settings.
 910      api = $.extend( new api.Values(), api );
 911  
 912      /**
 913       * Get all customize settings.
 914       *
 915       * @alias wp.customize.get
 916       *
 917       * @return {object}
 918       */
 919      api.get = function() {
 920          var result = {};
 921  
 922          this.each( function( obj, key ) {
 923              result[ key ] = obj.get();
 924          });
 925  
 926          return result;
 927      };
 928  
 929      /**
 930       * Utility function namespace
 931       *
 932       * @namespace wp.customize.utils
 933       */
 934      api.utils = {};
 935  
 936      /**
 937       * Parse query string.
 938       *
 939       * @since 4.7.0
 940       * @access public
 941       *
 942       * @alias wp.customize.utils.parseQueryString
 943       *
 944       * @param {string} queryString Query string.
 945       * @returns {object} Parsed query string.
 946       */
 947      api.utils.parseQueryString = function parseQueryString( queryString ) {
 948          var queryParams = {};
 949          _.each( queryString.split( '&' ), function( pair ) {
 950              var parts, key, value;
 951              parts = pair.split( '=', 2 );
 952              if ( ! parts[0] ) {
 953                  return;
 954              }
 955              key = decodeURIComponent( parts[0].replace( /\+/g, ' ' ) );
 956              key = key.replace( / /g, '_' ); // What PHP does.
 957              if ( _.isUndefined( parts[1] ) ) {
 958                  value = null;
 959              } else {
 960                  value = decodeURIComponent( parts[1].replace( /\+/g, ' ' ) );
 961              }
 962              queryParams[ key ] = value;
 963          } );
 964          return queryParams;
 965      };
 966  
 967      /**
 968       * Expose the API publicly on window.wp.customize
 969       *
 970       * @namespace wp.customize
 971       */
 972      exports.customize = api;
 973  })( wp, jQuery );


Generated: Tue Sep 17 01:00:03 2019 Cross-referenced by PHPXref 0.7.1