aboutsummaryrefslogtreecommitdiff
path: root/srcs/wordpress/wp-admin/js/customize-controls.js
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/wordpress/wp-admin/js/customize-controls.js')
-rw-r--r--srcs/wordpress/wp-admin/js/customize-controls.js9270
1 files changed, 0 insertions, 9270 deletions
diff --git a/srcs/wordpress/wp-admin/js/customize-controls.js b/srcs/wordpress/wp-admin/js/customize-controls.js
deleted file mode 100644
index 2edc498..0000000
--- a/srcs/wordpress/wp-admin/js/customize-controls.js
+++ /dev/null
@@ -1,9270 +0,0 @@
-/**
- * @output wp-admin/js/customize-controls.js
- */
-
-/* global _wpCustomizeHeader, _wpCustomizeBackground, _wpMediaViewsL10n, MediaElementPlayer, console, confirm */
-(function( exports, $ ){
- var Container, focus, normalizedTransitionendEventName, api = wp.customize;
-
- api.OverlayNotification = api.Notification.extend(/** @lends wp.customize.OverlayNotification.prototype */{
-
- /**
- * Whether the notification should show a loading spinner.
- *
- * @since 4.9.0
- * @var {boolean}
- */
- loading: false,
-
- /**
- * A notification that is displayed in a full-screen overlay.
- *
- * @constructs wp.customize.OverlayNotification
- * @augments wp.customize.Notification
- *
- * @since 4.9.0
- *
- * @param {string} code - Code.
- * @param {object} params - Params.
- */
- initialize: function( code, params ) {
- var notification = this;
- api.Notification.prototype.initialize.call( notification, code, params );
- notification.containerClasses += ' notification-overlay';
- if ( notification.loading ) {
- notification.containerClasses += ' notification-loading';
- }
- },
-
- /**
- * Render notification.
- *
- * @since 4.9.0
- *
- * @return {jQuery} Notification container.
- */
- render: function() {
- var li = api.Notification.prototype.render.call( this );
- li.on( 'keydown', _.bind( this.handleEscape, this ) );
- return li;
- },
-
- /**
- * Stop propagation on escape key presses, but also dismiss notification if it is dismissible.
- *
- * @since 4.9.0
- *
- * @param {jQuery.Event} event - Event.
- * @returns {void}
- */
- handleEscape: function( event ) {
- var notification = this;
- if ( 27 === event.which ) {
- event.stopPropagation();
- if ( notification.dismissible && notification.parent ) {
- notification.parent.remove( notification.code );
- }
- }
- }
- });
-
- api.Notifications = api.Values.extend(/** @lends wp.customize.Notifications.prototype */{
-
- /**
- * Whether the alternative style should be used.
- *
- * @since 4.9.0
- * @type {boolean}
- */
- alt: false,
-
- /**
- * The default constructor for items of the collection.
- *
- * @since 4.9.0
- * @type {object}
- */
- defaultConstructor: api.Notification,
-
- /**
- * A collection of observable notifications.
- *
- * @since 4.9.0
- *
- * @constructs wp.customize.Notifications
- * @augments wp.customize.Values
- *
- * @param {object} options - Options.
- * @param {jQuery} [options.container] - Container element for notifications. This can be injected later.
- * @param {boolean} [options.alt] - Whether alternative style should be used when rendering notifications.
- *
- * @returns {void}
- */
- initialize: function( options ) {
- var collection = this;
-
- api.Values.prototype.initialize.call( collection, options );
-
- _.bindAll( collection, 'constrainFocus' );
-
- // Keep track of the order in which the notifications were added for sorting purposes.
- collection._addedIncrement = 0;
- collection._addedOrder = {};
-
- // Trigger change event when notification is added or removed.
- collection.bind( 'add', function( notification ) {
- collection.trigger( 'change', notification );
- });
- collection.bind( 'removed', function( notification ) {
- collection.trigger( 'change', notification );
- });
- },
-
- /**
- * Get the number of notifications added.
- *
- * @since 4.9.0
- * @return {number} Count of notifications.
- */
- count: function() {
- return _.size( this._value );
- },
-
- /**
- * Add notification to the collection.
- *
- * @since 4.9.0
- *
- * @param {string|wp.customize.Notification} notification - Notification object to add. Alternatively code may be supplied, and in that case the second notificationObject argument must be supplied.
- * @param {wp.customize.Notification} [notificationObject] - Notification to add when first argument is the code string.
- * @returns {wp.customize.Notification} Added notification (or existing instance if it was already added).
- */
- add: function( notification, notificationObject ) {
- var collection = this, code, instance;
- if ( 'string' === typeof notification ) {
- code = notification;
- instance = notificationObject;
- } else {
- code = notification.code;
- instance = notification;
- }
- if ( ! collection.has( code ) ) {
- collection._addedIncrement += 1;
- collection._addedOrder[ code ] = collection._addedIncrement;
- }
- return api.Values.prototype.add.call( collection, code, instance );
- },
-
- /**
- * Add notification to the collection.
- *
- * @since 4.9.0
- * @param {string} code - Notification code to remove.
- * @return {api.Notification} Added instance (or existing instance if it was already added).
- */
- remove: function( code ) {
- var collection = this;
- delete collection._addedOrder[ code ];
- return api.Values.prototype.remove.call( this, code );
- },
-
- /**
- * Get list of notifications.
- *
- * Notifications may be sorted by type followed by added time.
- *
- * @since 4.9.0
- * @param {object} args - Args.
- * @param {boolean} [args.sort=false] - Whether to return the notifications sorted.
- * @return {Array.<wp.customize.Notification>} Notifications.
- */
- get: function( args ) {
- var collection = this, notifications, errorTypePriorities, params;
- notifications = _.values( collection._value );
-
- params = _.extend(
- { sort: false },
- args
- );
-
- if ( params.sort ) {
- errorTypePriorities = { error: 4, warning: 3, success: 2, info: 1 };
- notifications.sort( function( a, b ) {
- var aPriority = 0, bPriority = 0;
- if ( ! _.isUndefined( errorTypePriorities[ a.type ] ) ) {
- aPriority = errorTypePriorities[ a.type ];
- }
- if ( ! _.isUndefined( errorTypePriorities[ b.type ] ) ) {
- bPriority = errorTypePriorities[ b.type ];
- }
- if ( aPriority !== bPriority ) {
- return bPriority - aPriority; // Show errors first.
- }
- return collection._addedOrder[ b.code ] - collection._addedOrder[ a.code ]; // Show newer notifications higher.
- });
- }
-
- return notifications;
- },
-
- /**
- * Render notifications area.
- *
- * @since 4.9.0
- * @returns {void}
- */
- render: function() {
- var collection = this,
- notifications, hadOverlayNotification = false, hasOverlayNotification, overlayNotifications = [],
- previousNotificationsByCode = {},
- listElement, focusableElements;
-
- // Short-circuit if there are no container to render into.
- if ( ! collection.container || ! collection.container.length ) {
- return;
- }
-
- notifications = collection.get( { sort: true } );
- collection.container.toggle( 0 !== notifications.length );
-
- // Short-circuit if there are no changes to the notifications.
- if ( collection.container.is( collection.previousContainer ) && _.isEqual( notifications, collection.previousNotifications ) ) {
- return;
- }
-
- // Make sure list is part of the container.
- listElement = collection.container.children( 'ul' ).first();
- if ( ! listElement.length ) {
- listElement = $( '<ul></ul>' );
- collection.container.append( listElement );
- }
-
- // Remove all notifications prior to re-rendering.
- listElement.find( '> [data-code]' ).remove();
-
- _.each( collection.previousNotifications, function( notification ) {
- previousNotificationsByCode[ notification.code ] = notification;
- });
-
- // Add all notifications in the sorted order.
- _.each( notifications, function( notification ) {
- var notificationContainer;
- if ( wp.a11y && ( ! previousNotificationsByCode[ notification.code ] || ! _.isEqual( notification.message, previousNotificationsByCode[ notification.code ].message ) ) ) {
- wp.a11y.speak( notification.message, 'assertive' );
- }
- notificationContainer = $( notification.render() );
- notification.container = notificationContainer;
- listElement.append( notificationContainer ); // @todo Consider slideDown() as enhancement.
-
- if ( notification.extended( api.OverlayNotification ) ) {
- overlayNotifications.push( notification );
- }
- });
- hasOverlayNotification = Boolean( overlayNotifications.length );
-
- if ( collection.previousNotifications ) {
- hadOverlayNotification = Boolean( _.find( collection.previousNotifications, function( notification ) {
- return notification.extended( api.OverlayNotification );
- } ) );
- }
-
- if ( hasOverlayNotification !== hadOverlayNotification ) {
- $( document.body ).toggleClass( 'customize-loading', hasOverlayNotification );
- collection.container.toggleClass( 'has-overlay-notifications', hasOverlayNotification );
- if ( hasOverlayNotification ) {
- collection.previousActiveElement = document.activeElement;
- $( document ).on( 'keydown', collection.constrainFocus );
- } else {
- $( document ).off( 'keydown', collection.constrainFocus );
- }
- }
-
- if ( hasOverlayNotification ) {
- collection.focusContainer = overlayNotifications[ overlayNotifications.length - 1 ].container;
- collection.focusContainer.prop( 'tabIndex', -1 );
- focusableElements = collection.focusContainer.find( ':focusable' );
- if ( focusableElements.length ) {
- focusableElements.first().focus();
- } else {
- collection.focusContainer.focus();
- }
- } else if ( collection.previousActiveElement ) {
- $( collection.previousActiveElement ).focus();
- collection.previousActiveElement = null;
- }
-
- collection.previousNotifications = notifications;
- collection.previousContainer = collection.container;
- collection.trigger( 'rendered' );
- },
-
- /**
- * Constrain focus on focus container.
- *
- * @since 4.9.0
- *
- * @param {jQuery.Event} event - Event.
- * @returns {void}
- */
- constrainFocus: function constrainFocus( event ) {
- var collection = this, focusableElements;
-
- // Prevent keys from escaping.
- event.stopPropagation();
-
- if ( 9 !== event.which ) { // Tab key.
- return;
- }
-
- focusableElements = collection.focusContainer.find( ':focusable' );
- if ( 0 === focusableElements.length ) {
- focusableElements = collection.focusContainer;
- }
-
- if ( ! $.contains( collection.focusContainer[0], event.target ) || ! $.contains( collection.focusContainer[0], document.activeElement ) ) {
- event.preventDefault();
- focusableElements.first().focus();
- } else if ( focusableElements.last().is( event.target ) && ! event.shiftKey ) {
- event.preventDefault();
- focusableElements.first().focus();
- } else if ( focusableElements.first().is( event.target ) && event.shiftKey ) {
- event.preventDefault();
- focusableElements.last().focus();
- }
- }
- });
-
- api.Setting = api.Value.extend(/** @lends wp.customize.Setting.prototype */{
-
- /**
- * Default params.
- *
- * @since 4.9.0
- * @var {object}
- */
- defaults: {
- transport: 'refresh',
- dirty: false
- },
-
- /**
- * A Customizer Setting.
- *
- * A setting is WordPress data (theme mod, option, menu, etc.) that the user can
- * draft changes to in the Customizer.
- *
- * @see PHP class WP_Customize_Setting.
- *
- * @constructs wp.customize.Setting
- * @augments wp.customize.Value
- *
- * @since 3.4.0
- *
- * @param {string} id - The setting ID.
- * @param {*} value - The initial value of the setting.
- * @param {object} [options={}] - Options.
- * @param {string} [options.transport=refresh] - The transport to use for previewing. Supports 'refresh' and 'postMessage'.
- * @param {boolean} [options.dirty=false] - Whether the setting should be considered initially dirty.
- * @param {object} [options.previewer] - The Previewer instance to sync with. Defaults to wp.customize.previewer.
- */
- initialize: function( id, value, options ) {
- var setting = this, params;
- params = _.extend(
- { previewer: api.previewer },
- setting.defaults,
- options || {}
- );
-
- api.Value.prototype.initialize.call( setting, value, params );
-
- setting.id = id;
- setting._dirty = params.dirty; // The _dirty property is what the Customizer reads from.
- setting.notifications = new api.Notifications();
-
- // Whenever the setting's value changes, refresh the preview.
- setting.bind( setting.preview );
- },
-
- /**
- * Refresh the preview, respective of the setting's refresh policy.
- *
- * If the preview hasn't sent a keep-alive message and is likely
- * disconnected by having navigated to a non-allowed URL, then the
- * refresh transport will be forced when postMessage is the transport.
- * Note that postMessage does not throw an error when the recipient window
- * fails to match the origin window, so using try/catch around the
- * previewer.send() call to then fallback to refresh will not work.
- *
- * @since 3.4.0
- * @access public
- *
- * @returns {void}
- */
- preview: function() {
- var setting = this, transport;
- transport = setting.transport;
-
- if ( 'postMessage' === transport && ! api.state( 'previewerAlive' ).get() ) {
- transport = 'refresh';
- }
-
- if ( 'postMessage' === transport ) {
- setting.previewer.send( 'setting', [ setting.id, setting() ] );
- } else if ( 'refresh' === transport ) {
- setting.previewer.refresh();
- }
- },
-
- /**
- * Find controls associated with this setting.
- *
- * @since 4.6.0
- * @returns {wp.customize.Control[]} Controls associated with setting.
- */
- findControls: function() {
- var setting = this, controls = [];
- api.control.each( function( control ) {
- _.each( control.settings, function( controlSetting ) {
- if ( controlSetting.id === setting.id ) {
- controls.push( control );
- }
- } );
- } );
- return controls;
- }
- });
-
- /**
- * Current change count.
- *
- * @alias wp.customize._latestRevision
- *
- * @since 4.7.0
- * @type {number}
- * @protected
- */
- api._latestRevision = 0;
-
- /**
- * Last revision that was saved.
- *
- * @alias wp.customize._lastSavedRevision
- *
- * @since 4.7.0
- * @type {number}
- * @protected
- */
- api._lastSavedRevision = 0;
-
- /**
- * Latest revisions associated with the updated setting.
- *
- * @alias wp.customize._latestSettingRevisions
- *
- * @since 4.7.0
- * @type {object}
- * @protected
- */
- api._latestSettingRevisions = {};
-
- /*
- * Keep track of the revision associated with each updated setting so that
- * requestChangesetUpdate knows which dirty settings to include. Also, once
- * ready is triggered and all initial settings have been added, increment
- * revision for each newly-created initially-dirty setting so that it will
- * also be included in changeset update requests.
- */
- api.bind( 'change', function incrementChangedSettingRevision( setting ) {
- api._latestRevision += 1;
- api._latestSettingRevisions[ setting.id ] = api._latestRevision;
- } );
- api.bind( 'ready', function() {
- api.bind( 'add', function incrementCreatedSettingRevision( setting ) {
- if ( setting._dirty ) {
- api._latestRevision += 1;
- api._latestSettingRevisions[ setting.id ] = api._latestRevision;
- }
- } );
- } );
-
- /**
- * Get the dirty setting values.
- *
- * @alias wp.customize.dirtyValues
- *
- * @since 4.7.0
- * @access public
- *
- * @param {object} [options] Options.
- * @param {boolean} [options.unsaved=false] Whether only values not saved yet into a changeset will be returned (differential changes).
- * @returns {object} Dirty setting values.
- */
- api.dirtyValues = function dirtyValues( options ) {
- var values = {};
- api.each( function( setting ) {
- var settingRevision;
-
- if ( ! setting._dirty ) {
- return;
- }
-
- settingRevision = api._latestSettingRevisions[ setting.id ];
-
- // Skip including settings that have already been included in the changeset, if only requesting unsaved.
- if ( api.state( 'changesetStatus' ).get() && ( options && options.unsaved ) && ( _.isUndefined( settingRevision ) || settingRevision <= api._lastSavedRevision ) ) {
- return;
- }
-
- values[ setting.id ] = setting.get();
- } );
- return values;
- };
-
- /**
- * Request updates to the changeset.
- *
- * @alias wp.customize.requestChangesetUpdate
- *
- * @since 4.7.0
- * @access public
- *
- * @param {object} [changes] - Mapping of setting IDs to setting params each normally including a value property, or mapping to null.
- * If not provided, then the changes will still be obtained from unsaved dirty settings.
- * @param {object} [args] - Additional options for the save request.
- * @param {boolean} [args.autosave=false] - Whether changes will be stored in autosave revision if the changeset has been promoted from an auto-draft.
- * @param {boolean} [args.force=false] - Send request to update even when there are no changes to submit. This can be used to request the latest status of the changeset on the server.
- * @param {string} [args.title] - Title to update in the changeset. Optional.
- * @param {string} [args.date] - Date to update in the changeset. Optional.
- * @returns {jQuery.Promise} Promise resolving with the response data.
- */
- api.requestChangesetUpdate = function requestChangesetUpdate( changes, args ) {
- var deferred, request, submittedChanges = {}, data, submittedArgs;
- deferred = new $.Deferred();
-
- // Prevent attempting changeset update while request is being made.
- if ( 0 !== api.state( 'processing' ).get() ) {
- deferred.reject( 'already_processing' );
- return deferred.promise();
- }
-
- submittedArgs = _.extend( {
- title: null,
- date: null,
- autosave: false,
- force: false
- }, args );
-
- if ( changes ) {
- _.extend( submittedChanges, changes );
- }
-
- // Ensure all revised settings (changes pending save) are also included, but not if marked for deletion in changes.
- _.each( api.dirtyValues( { unsaved: true } ), function( dirtyValue, settingId ) {
- if ( ! changes || null !== changes[ settingId ] ) {
- submittedChanges[ settingId ] = _.extend(
- {},
- submittedChanges[ settingId ] || {},
- { value: dirtyValue }
- );
- }
- } );
-
- // Allow plugins to attach additional params to the settings.
- api.trigger( 'changeset-save', submittedChanges, submittedArgs );
-
- // Short-circuit when there are no pending changes.
- if ( ! submittedArgs.force && _.isEmpty( submittedChanges ) && null === submittedArgs.title && null === submittedArgs.date ) {
- deferred.resolve( {} );
- return deferred.promise();
- }
-
- // A status would cause a revision to be made, and for this wp.customize.previewer.save() should be used. Status is also disallowed for revisions regardless.
- if ( submittedArgs.status ) {
- return deferred.reject( { code: 'illegal_status_in_changeset_update' } ).promise();
- }
-
- // Dates not beung allowed for revisions are is a technical limitation of post revisions.
- if ( submittedArgs.date && submittedArgs.autosave ) {
- return deferred.reject( { code: 'illegal_autosave_with_date_gmt' } ).promise();
- }
-
- // Make sure that publishing a changeset waits for all changeset update requests to complete.
- api.state( 'processing' ).set( api.state( 'processing' ).get() + 1 );
- deferred.always( function() {
- api.state( 'processing' ).set( api.state( 'processing' ).get() - 1 );
- } );
-
- // Ensure that if any plugins add data to save requests by extending query() that they get included here.
- data = api.previewer.query( { excludeCustomizedSaved: true } );
- delete data.customized; // Being sent in customize_changeset_data instead.
- _.extend( data, {
- nonce: api.settings.nonce.save,
- customize_theme: api.settings.theme.stylesheet,
- customize_changeset_data: JSON.stringify( submittedChanges )
- } );
- if ( null !== submittedArgs.title ) {
- data.customize_changeset_title = submittedArgs.title;
- }
- if ( null !== submittedArgs.date ) {
- data.customize_changeset_date = submittedArgs.date;
- }
- if ( false !== submittedArgs.autosave ) {
- data.customize_changeset_autosave = 'true';
- }
-
- // Allow plugins to modify the params included with the save request.
- api.trigger( 'save-request-params', data );
-
- request = wp.ajax.post( 'customize_save', data );
-
- request.done( function requestChangesetUpdateDone( data ) {
- var savedChangesetValues = {};
-
- // Ensure that all settings updated subsequently will be included in the next changeset update request.
- api._lastSavedRevision = Math.max( api._latestRevision, api._lastSavedRevision );
-
- api.state( 'changesetStatus' ).set( data.changeset_status );
-
- if ( data.changeset_date ) {
- api.state( 'changesetDate' ).set( data.changeset_date );
- }
-
- deferred.resolve( data );
- api.trigger( 'changeset-saved', data );
-
- if ( data.setting_validities ) {
- _.each( data.setting_validities, function( validity, settingId ) {
- if ( true === validity && _.isObject( submittedChanges[ settingId ] ) && ! _.isUndefined( submittedChanges[ settingId ].value ) ) {
- savedChangesetValues[ settingId ] = submittedChanges[ settingId ].value;
- }
- } );
- }
-
- api.previewer.send( 'changeset-saved', _.extend( {}, data, { saved_changeset_values: savedChangesetValues } ) );
- } );
- request.fail( function requestChangesetUpdateFail( data ) {
- deferred.reject( data );
- api.trigger( 'changeset-error', data );
- } );
- request.always( function( data ) {
- if ( data.setting_validities ) {
- api._handleSettingValidities( {
- settingValidities: data.setting_validities
- } );
- }
- } );
-
- return deferred.promise();
- };
-
- /**
- * Watch all changes to Value properties, and bubble changes to parent Values instance
- *
- * @alias wp.customize.utils.bubbleChildValueChanges
- *
- * @since 4.1.0
- *
- * @param {wp.customize.Class} instance
- * @param {Array} properties The names of the Value instances to watch.
- */
- api.utils.bubbleChildValueChanges = function ( instance, properties ) {
- $.each( properties, function ( i, key ) {
- instance[ key ].bind( function ( to, from ) {
- if ( instance.parent && to !== from ) {
- instance.parent.trigger( 'change', instance );
- }
- } );
- } );
- };
-
- /**
- * Expand a panel, section, or control and focus on the first focusable element.
- *
- * @alias wp.customize~focus
- *
- * @since 4.1.0
- *
- * @param {Object} [params]
- * @param {Function} [params.completeCallback]
- */
- focus = function ( params ) {
- var construct, completeCallback, focus, focusElement;
- construct = this;
- params = params || {};
- focus = function () {
- var focusContainer;
- if ( ( construct.extended( api.Panel ) || construct.extended( api.Section ) ) && construct.expanded && construct.expanded() ) {
- focusContainer = construct.contentContainer;
- } else {
- focusContainer = construct.container;
- }
-
- focusElement = focusContainer.find( '.control-focus:first' );
- if ( 0 === focusElement.length ) {
- // Note that we can't use :focusable due to a jQuery UI issue. See: https://github.com/jquery/jquery-ui/pull/1583
- focusElement = focusContainer.find( 'input, select, textarea, button, object, a[href], [tabindex]' ).filter( ':visible' ).first();
- }
- focusElement.focus();
- };
- if ( params.completeCallback ) {
- completeCallback = params.completeCallback;
- params.completeCallback = function () {
- focus();
- completeCallback();
- };
- } else {
- params.completeCallback = focus;
- }
-
- api.state( 'paneVisible' ).set( true );
- if ( construct.expand ) {
- construct.expand( params );
- } else {
- params.completeCallback();
- }
- };
-
- /**
- * Stable sort for Panels, Sections, and Controls.
- *
- * If a.priority() === b.priority(), then sort by their respective params.instanceNumber.
- *
- * @alias wp.customize.utils.prioritySort
- *
- * @since 4.1.0
- *
- * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} a
- * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} b
- * @returns {Number}
- */
- api.utils.prioritySort = function ( a, b ) {
- if ( a.priority() === b.priority() && typeof a.params.instanceNumber === 'number' && typeof b.params.instanceNumber === 'number' ) {
- return a.params.instanceNumber - b.params.instanceNumber;
- } else {
- return a.priority() - b.priority();
- }
- };
-
- /**
- * Return whether the supplied Event object is for a keydown event but not the Enter key.
- *
- * @alias wp.customize.utils.isKeydownButNotEnterEvent
- *
- * @since 4.1.0
- *
- * @param {jQuery.Event} event
- * @returns {boolean}
- */
- api.utils.isKeydownButNotEnterEvent = function ( event ) {
- return ( 'keydown' === event.type && 13 !== event.which );
- };
-
- /**
- * Return whether the two lists of elements are the same and are in the same order.
- *
- * @alias wp.customize.utils.areElementListsEqual
- *
- * @since 4.1.0
- *
- * @param {Array|jQuery} listA
- * @param {Array|jQuery} listB
- * @returns {boolean}
- */
- api.utils.areElementListsEqual = function ( listA, listB ) {
- var equal = (
- listA.length === listB.length && // if lists are different lengths, then naturally they are not equal
- -1 === _.indexOf( _.map( // are there any false values in the list returned by map?
- _.zip( listA, listB ), // pair up each element between the two lists
- function ( pair ) {
- return $( pair[0] ).is( pair[1] ); // compare to see if each pair are equal
- }
- ), false ) // check for presence of false in map's return value
- );
- return equal;
- };
-
- /**
- * Highlight the existence of a button.
- *
- * This function reminds the user of a button represented by the specified
- * UI element, after an optional delay. If the user focuses the element
- * before the delay passes, the reminder is canceled.
- *
- * @alias wp.customize.utils.highlightButton
- *
- * @since 4.9.0
- *
- * @param {jQuery} button - The element to highlight.
- * @param {object} [options] - Options.
- * @param {number} [options.delay=0] - Delay in milliseconds.
- * @param {jQuery} [options.focusTarget] - A target for user focus that defaults to the highlighted element.
- * If the user focuses the target before the delay passes, the reminder
- * is canceled. This option exists to accommodate compound buttons
- * containing auxiliary UI, such as the Publish button augmented with a
- * Settings button.
- * @returns {Function} An idempotent function that cancels the reminder.
- */
- api.utils.highlightButton = function highlightButton( button, options ) {
- var animationClass = 'button-see-me',
- canceled = false,
- params;
-
- params = _.extend(
- {
- delay: 0,
- focusTarget: button
- },
- options
- );
-
- function cancelReminder() {
- canceled = true;
- }
-
- params.focusTarget.on( 'focusin', cancelReminder );
- setTimeout( function() {
- params.focusTarget.off( 'focusin', cancelReminder );
-
- if ( ! canceled ) {
- button.addClass( animationClass );
- button.one( 'animationend', function() {
- /*
- * Remove animation class to avoid situations in Customizer where
- * DOM nodes are moved (re-inserted) and the animation repeats.
- */
- button.removeClass( animationClass );
- } );
- }
- }, params.delay );
-
- return cancelReminder;
- };
-
- /**
- * Get current timestamp adjusted for server clock time.
- *
- * Same functionality as the `current_time( 'mysql', false )` function in PHP.
- *
- * @alias wp.customize.utils.getCurrentTimestamp
- *
- * @since 4.9.0
- *
- * @returns {int} Current timestamp.
- */
- api.utils.getCurrentTimestamp = function getCurrentTimestamp() {
- var currentDate, currentClientTimestamp, timestampDifferential;
- currentClientTimestamp = _.now();
- currentDate = new Date( api.settings.initialServerDate.replace( /-/g, '/' ) );
- timestampDifferential = currentClientTimestamp - api.settings.initialClientTimestamp;
- timestampDifferential += api.settings.initialClientTimestamp - api.settings.initialServerTimestamp;
- currentDate.setTime( currentDate.getTime() + timestampDifferential );
- return currentDate.getTime();
- };
-
- /**
- * Get remaining time of when the date is set.
- *
- * @alias wp.customize.utils.getRemainingTime
- *
- * @since 4.9.0
- *
- * @param {string|int|Date} datetime - Date time or timestamp of the future date.
- * @return {int} remainingTime - Remaining time in milliseconds.
- */
- api.utils.getRemainingTime = function getRemainingTime( datetime ) {
- var millisecondsDivider = 1000, remainingTime, timestamp;
- if ( datetime instanceof Date ) {
- timestamp = datetime.getTime();
- } else if ( 'string' === typeof datetime ) {
- timestamp = ( new Date( datetime.replace( /-/g, '/' ) ) ).getTime();
- } else {
- timestamp = datetime;
- }
-
- remainingTime = timestamp - api.utils.getCurrentTimestamp();
- remainingTime = Math.ceil( remainingTime / millisecondsDivider );
- return remainingTime;
- };
-
- /**
- * Return browser supported `transitionend` event name.
- *
- * @since 4.7.0
- *
- * @ignore
- *
- * @returns {string|null} Normalized `transitionend` event name or null if CSS transitions are not supported.
- */
- normalizedTransitionendEventName = (function () {
- var el, transitions, prop;
- el = document.createElement( 'div' );
- transitions = {
- 'transition' : 'transitionend',
- 'OTransition' : 'oTransitionEnd',
- 'MozTransition' : 'transitionend',
- 'WebkitTransition': 'webkitTransitionEnd'
- };
- prop = _.find( _.keys( transitions ), function( prop ) {
- return ! _.isUndefined( el.style[ prop ] );
- } );
- if ( prop ) {
- return transitions[ prop ];
- } else {
- return null;
- }
- })();
-
- Container = api.Class.extend(/** @lends wp.customize~Container.prototype */{
- defaultActiveArguments: { duration: 'fast', completeCallback: $.noop },
- defaultExpandedArguments: { duration: 'fast', completeCallback: $.noop },
- containerType: 'container',
- defaults: {
- title: '',
- description: '',
- priority: 100,
- type: 'default',
- content: null,
- active: true,
- instanceNumber: null
- },
-
- /**
- * Base class for Panel and Section.
- *
- * @constructs wp.customize~Container
- * @augments wp.customize.Class
- *
- * @since 4.1.0
- *
- * @borrows wp.customize~focus as focus
- *
- * @param {string} id - The ID for the container.
- * @param {object} options - Object containing one property: params.
- * @param {string} options.title - Title shown when panel is collapsed and expanded.
- * @param {string} [options.description] - Description shown at the top of the panel.
- * @param {number} [options.priority=100] - The sort priority for the panel.
- * @param {string} [options.templateId] - Template selector for container.
- * @param {string} [options.type=default] - The type of the panel. See wp.customize.panelConstructor.
- * @param {string} [options.content] - The markup to be used for the panel container. If empty, a JS template is used.
- * @param {boolean} [options.active=true] - Whether the panel is active or not.
- * @param {object} [options.params] - Deprecated wrapper for the above properties.
- */
- initialize: function ( id, options ) {
- var container = this;
- container.id = id;
-
- if ( ! Container.instanceCounter ) {
- Container.instanceCounter = 0;
- }
- Container.instanceCounter++;
-
- $.extend( container, {
- params: _.defaults(
- options.params || options, // Passing the params is deprecated.
- container.defaults
- )
- } );
- if ( ! container.params.instanceNumber ) {
- container.params.instanceNumber = Container.instanceCounter;
- }
- container.notifications = new api.Notifications();
- container.templateSelector = container.params.templateId || 'customize-' + container.containerType + '-' + container.params.type;
- container.container = $( container.params.content );
- if ( 0 === container.container.length ) {
- container.container = $( container.getContainer() );
- }
- container.headContainer = container.container;
- container.contentContainer = container.getContent();
- container.container = container.container.add( container.contentContainer );
-
- container.deferred = {
- embedded: new $.Deferred()
- };
- container.priority = new api.Value();
- container.active = new api.Value();
- container.activeArgumentsQueue = [];
- container.expanded = new api.Value();
- container.expandedArgumentsQueue = [];
-
- container.active.bind( function ( active ) {
- var args = container.activeArgumentsQueue.shift();
- args = $.extend( {}, container.defaultActiveArguments, args );
- active = ( active && container.isContextuallyActive() );
- container.onChangeActive( active, args );
- });
- container.expanded.bind( function ( expanded ) {
- var args = container.expandedArgumentsQueue.shift();
- args = $.extend( {}, container.defaultExpandedArguments, args );
- container.onChangeExpanded( expanded, args );
- });
-
- container.deferred.embedded.done( function () {
- container.setupNotifications();
- container.attachEvents();
- });
-
- api.utils.bubbleChildValueChanges( container, [ 'priority', 'active' ] );
-
- container.priority.set( container.params.priority );
- container.active.set( container.params.active );
- container.expanded.set( false );
- },
-
- /**
- * Get the element that will contain the notifications.
- *
- * @since 4.9.0
- * @returns {jQuery} Notification container element.
- */
- getNotificationsContainerElement: function() {
- var container = this;
- return container.contentContainer.find( '.customize-control-notifications-container:first' );
- },
-
- /**
- * Set up notifications.
- *
- * @since 4.9.0
- * @returns {void}
- */
- setupNotifications: function() {
- var container = this, renderNotifications;
- container.notifications.container = container.getNotificationsContainerElement();
-
- // Render notifications when they change and when the construct is expanded.
- renderNotifications = function() {
- if ( container.expanded.get() ) {
- container.notifications.render();
- }
- };
- container.expanded.bind( renderNotifications );
- renderNotifications();
- container.notifications.bind( 'change', _.debounce( renderNotifications ) );
- },
-
- /**
- * @since 4.1.0
- *
- * @abstract
- */
- ready: function() {},
-
- /**
- * Get the child models associated with this parent, sorting them by their priority Value.
- *
- * @since 4.1.0
- *
- * @param {String} parentType
- * @param {String} childType
- * @returns {Array}
- */
- _children: function ( parentType, childType ) {
- var parent = this,
- children = [];
- api[ childType ].each( function ( child ) {
- if ( child[ parentType ].get() === parent.id ) {
- children.push( child );
- }
- } );
- children.sort( api.utils.prioritySort );
- return children;
- },