: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
ids = slice.call( arguments ),
// If the last argument is a callback, bind it to .done().
if ( typeof ids[ ids.length - 1 ] === 'function' ) {
* Create a stack of deferred objects for each item that is not
* yet available, and invoke the supplied callback when they are.
$.when.apply( $, $.map( ids, function( id ) {
* The requested item is not available yet, create a deferred
* object to resolve when it becomes available.
return self._deferreds[ id ] = self._deferreds[ id ] || $.Deferred();
var values = $.map( ids, function( id ) {
// If a value is missing, we've used at least one expired deferred.
// Call Values.when again to generate a new deferred.
if ( values.length !== ids.length ) {
self.when.apply( self, ids ).done( function() {
dfd.resolveWith( self, values );
dfd.resolveWith( self, values );
* A helper function to propagate a 'change' event from an item
* to the collection itself.
this.parent.trigger( 'change', this );
// Create a global events bus on the Customizer.
$.extend( api.Values.prototype, api.Events );
* Cast a string to a jQuery collection if it isn't already.
* @param {string|jQuery collection} element
api.ensure = function( element ) {
return typeof element === 'string' ? $( element ) : element;
* An observable value that syncs with an element.
* Handles inputs, selects, and textareas by default.
* @alias wp.customize.Element
* @augments wp.customize.Value
* @augments wp.customize.Class
api.Element = api.Value.extend(/** @lends wp.customize.Element */{
initialize: function( element, options ) {
synchronizer = api.Element.synchronizer.html,
this.element = api.ensure( element );
if ( this.element.is( 'input, select, textarea' ) ) {
type = this.element.prop( 'type' );
this.events += ' change input';
synchronizer = api.Element.synchronizer.val;
if ( this.element.is( 'input' ) && api.Element.synchronizer[ type ] ) {
synchronizer = api.Element.synchronizer[ type ];
api.Value.prototype.initialize.call( this, null, $.extend( options || {}, synchronizer ) );
this._value = this.get();
this.update = function( to ) {
if ( to !== refresh.call( self ) ) {
update.apply( this, arguments );
this.refresh = function() {
self.set( refresh.call( self ) );
this.bind( this.update );
this.element.on( this.events, this.refresh );
find: function( selector ) {
return $( selector, this.element );
api.Element.synchronizer = {};
$.each( [ 'html', 'val' ], function( index, method ) {
api.Element.synchronizer[ method ] = {
this.element[ method ]( to );
return this.element[ method ]();
api.Element.synchronizer.checkbox = {
this.element.prop( 'checked', to );
return this.element.prop( 'checked' );
api.Element.synchronizer.radio = {
this.element.filter( function() {
return this.value === to;
}).prop( 'checked', true );
return this.element.filter( ':checked' ).val();
$.support.postMessage = !! window.postMessage;
* A communicator for sending data from one window to another over postMessage.
* @alias wp.customize.Messenger
* @augments wp.customize.Class
* @mixes wp.customize.Events
api.Messenger = api.Class.extend(/** @lends wp.customize.Messenger.prototype */{
* @param {string} key Unique identifier.
* @param {mixed} initial Initial value.
* @param {mixed} options Options hash. Optional.
* @return {Value} Class instance of the Value.
add: function( key, initial, options ) {
return this[ key ] = new api.Value( initial, options );
* @param {Object} params - Parameters to configure the messenger.
* {string} params.url - The URL to communicate with.
* {window} params.targetWindow - The window instance to communicate with. Default window.parent.
* {string} params.channel - If provided, will send the channel with each message and only accept messages a matching channel.
* @param {Object} options - Extend any instance parameter or method with this object.
initialize: function( params, options ) {
// Target the parent frame by default, but only if a parent frame exists.
var defaultTarget = window.parent === window ? null : window.parent;
$.extend( this, options || {} );
this.add( 'channel', params.channel );
this.add( 'url', params.url || '' );
this.add( 'origin', this.url() ).link( this.url ).setter( function( to ) {
var urlParser = document.createElement( 'a' );
// Port stripping needed by IE since it adds to host but not to event.origin.
return urlParser.protocol + '//' + urlParser.host.replace( /:(80|443)$/, '' );
// First add with no value.
this.add( 'targetWindow', null );
// This avoids SecurityErrors when setting a window object in x-origin iframe'd scenarios.
this.targetWindow.set = function( to ) {
to = this._setter.apply( this, arguments );
to = this.validate( to );
if ( null === to || from === to ) {
this.callbacks.fireWith( this, [ to, from ] );
this.targetWindow( params.targetWindow || defaultTarget );
* Since we want jQuery to treat the receive function as unique
* to this instance, we give the function a new guid.
* This will prevent every Messenger's receive function from being
* unbound when calling $.off( 'message', this.receive );
this.receive = this.receive.bind( this );
this.receive.guid = $.guid++;
$( window ).on( 'message', this.receive );
$( window ).off( 'message', this.receive );
* Receive data from the other window.
* @param {jQuery.Event} event Event with embedded data.
receive: function( event ) {
event = event.originalEvent;
if ( ! this.targetWindow || ! this.targetWindow() ) {
// Check to make sure the origin is valid.
if ( this.origin() && event.origin !== this.origin() ) {
// Ensure we have a string that's JSON.parse-able.
if ( typeof event.data !== 'string' || event.data[0] !== '{' ) {
message = JSON.parse( event.data );
// Check required message properties.
if ( ! message || ! message.id || typeof message.data === 'undefined' ) {
// Check if channel names match.
if ( ( message.channel || this.channel() ) && this.channel() !== message.channel ) {
this.trigger( message.id, message.data );
* Send data to the other window.
* @param {string} id The event name.
* @param {Object} data Data.
send: function( id, data ) {
data = typeof data === 'undefined' ? null : data;
if ( ! this.url() || ! this.targetWindow() ) {
message = { id: id, data: data };
message.channel = this.channel();
this.targetWindow().postMessage( JSON.stringify( message ), this.origin() );
// Add the Events mixin to api.Messenger.
$.extend( api.Messenger.prototype, api.Events );
* @augments wp.customize.Class
* @alias wp.customize.Notification
* @param {string} code - The error code.
* @param {object} params - Params.
* @param {string} params.message=null - The error message.
* @param {string} [params.type=error] - The notification type.
* @param {boolean} [params.fromServer=false] - Whether the notification was server-sent.
* @param {string} [params.setting=null] - The setting ID that the notification is related to.
* @param {*} [params.data=null] - Any additional data.
api.Notification = api.Class.extend(/** @lends wp.customize.Notification.prototype */{
* Template function for rendering the notification.
* This will be populated with template option or else it will be populated with template from the ID.
* ID for the template to render the notification.
templateId: 'customize-notification',
* Additional class names to add to the notification container.
* Initialize notification.
* @param {string} code - Notification code.
* @param {Object} params - Notification parameters.
* @param {string} params.message - Message.
* @param {string} [params.type=error] - Type.
* @param {string} [params.setting] - Related setting ID.
* @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId.
* @param {string} [params.templateId] - ID for template to render the notification.
* @param {string} [params.containerClasses] - Additional class names to add to the notification container.
* @param {boolean} [params.dismissible] - Whether the notification can be dismissed.
initialize: function( code, params ) {
_.extend( this, _params );
* Render the notification.
* @return {jQuery} Notification container element.
var notification = this, container, data;
if ( ! notification.template ) {
notification.template = wp.template( notification.templateId );
data = _.extend( {}, notification, {
alt: notification.parent && notification.parent.alt
container = $( notification.template( data ) );
if ( notification.dismissible ) {
container.find( '.notice-dismiss' ).on( 'click keydown', function( event ) {
if ( 'keydown' === event.type && 13 !== event.which ) {
if ( notification.parent ) {
notification.parent.remove( notification.code );
// The main API object is also a collection of all customizer settings.
api = $.extend( new api.Values(), api );
* Get all customize settings.
* @alias wp.customize.get
this.each( function( obj, key ) {
result[ key ] = obj.get();
* Utility function namespace
* @namespace wp.customize.utils
* @alias wp.customize.utils.parseQueryString
* @param {string} queryString Query string.
* @return {Object} Parsed query string.
api.utils.parseQueryString = function parseQueryString( queryString ) {
_.each( queryString.split( '&' ), function( pair ) {
parts = pair.split( '=', 2 );
key = decodeURIComponent( parts[0].replace( /\+/g, ' ' ) );
key = key.replace( / /g, '_' ); // What PHP does.
if ( _.isUndefined( parts[1] ) ) {
value = decodeURIComponent( parts[1].replace( /\+/g, ' ' ) );
queryParams[ key ] = value;
* Expose the API publicly on window.wp.customize
* @namespace wp.customize