]> scripts.mit.edu Git - autoinstalls/wordpress.git/blobdiff - wp-admin/js/customize-controls.js
WordPress 4.5
[autoinstalls/wordpress.git] / wp-admin / js / customize-controls.js
index e78d2c96c7f1aa9d6e0a1db4bda5dd92ede9a85e..5c21af6be4cf2a69b94cf3341d6a51fb0bd0fb82 100644 (file)
         * @since 4.1.0
         *
         * @param {Object}   [params]
-        * @param {Callback} [params.completeCallback]
+        * @param {Function} [params.completeCallback]
         */
        focus = function ( params ) {
-               var construct, completeCallback, focus;
+               var construct, completeCallback, focus, focusElement;
                construct = this;
                params = params || {};
                focus = function () {
                                focusContainer = construct.container;
                        }
 
-                       // Note that we can't use :focusable due to a jQuery UI issue. See: https://github.com/jquery/jquery-ui/pull/1583
-                       focusContainer.find( 'input, select, textarea, button, object, a[href], [tabindex]' ).filter( ':visible' ).first().focus();
+                       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;
                                                // Fix the height after browser resize.
                                                $( window ).on( 'resize.customizer-section', _.debounce( resizeContentHeight, 100 ) );
 
-                                               section._recalculateTopMargin();
+                                               setTimeout( _.bind( section._recalculateTopMargin, section ), 0 );
                                        };
                                }
 
                        settings = $.map( control.params.settings, function( value ) {
                                return value;
                        });
-                       api.apply( api, settings.concat( function () {
-                               var key;
 
+                       if ( 0 === settings.length ) {
+                               control.setting = null;
                                control.settings = {};
-                               for ( key in control.params.settings ) {
-                                       control.settings[ key ] = api( control.params.settings[ key ] );
-                               }
+                               control.embed();
+                       } else {
+                               api.apply( api, settings.concat( function() {
+                                       var key;
 
-                               control.setting = control.settings['default'] || null;
+                                       control.settings = {};
+                                       for ( key in control.params.settings ) {
+                                               control.settings[ key ] = api( control.params.settings[ key ] );
+                                       }
 
-                               control.embed();
-                       }) );
+                                       control.setting = control.settings['default'] || null;
+
+                                       control.embed();
+                               }) );
+                       }
 
                        // After the control is embedded on the page, invoke the "ready" method.
                        control.deferred.embedded.done( function () {
                        // Watch for changes to the section state
                        inject = function ( sectionId ) {
                                var parentContainer;
-                               if ( ! sectionId ) { // @todo allow a control to be embedded without a section, for instance a control embedded in the frontend
+                               if ( ! sectionId ) { // @todo allow a control to be embedded without a section, for instance a control embedded in the front end.
                                        return;
                                }
                                // Wait for the section to be registered
                                        control.pausePlayer();
                                });
 
-                       // Re-render whenever the control's setting changes.
-                       control.setting.bind( function () { control.renderContent(); } );
+                       control.setting.bind( function( value ) {
+
+                               // Send attachment information to the preview for possible use in `postMessage` transport.
+                               wp.media.attachment( value ).fetch().done( function() {
+                                       wp.customize.previewer.send( control.setting.id + '-attachment-data', this.attributes );
+                               } );
+
+                               // Re-render whenever the control's setting changes.
+                               control.renderContent();
+                       } );
                },
 
                pausePlayer: function () {
                                xInit = parseInt( control.params.width, 10 ),
                                yInit = parseInt( control.params.height, 10 ),
                                ratio = xInit / yInit,
-                               xImg  = realWidth,
-                               yImg  = realHeight,
+                               xImg  = xInit,
+                               yImg  = yInit,
                                x1, y1, imgSelectOptions;
 
                        controller.set( 'canSkipCrop', ! control.mustBeCropped( flexWidth, flexHeight, xInit, yInit, realWidth, realHeight ) );
 
-                       if ( xImg / yImg > ratio ) {
-                               yInit = yImg;
+                       if ( realWidth / realHeight > ratio ) {
+                               yInit = realHeight;
                                xInit = yInit * ratio;
                        } else {
-                               xInit = xImg;
+                               xInit = realWidth;
                                yInit = xInit / ratio;
                        }
 
-                       x1 = ( xImg - xInit ) / 2;
-                       y1 = ( yImg - yInit ) / 2;
+                       x1 = ( realWidth - xInit ) / 2;
+                       y1 = ( realHeight - yInit ) / 2;
 
                        imgSelectOptions = {
                                handles: true,
                                persistent: true,
                                imageWidth: realWidth,
                                imageHeight: realHeight,
+                               minWidth: xImg > xInit ? xInit : xImg,
+                               minHeight: yImg > yInit ? yInit : yImg,
                                x1: x1,
                                y1: y1,
                                x2: xInit + x1,
                        if ( flexHeight === false && flexWidth === false ) {
                                imgSelectOptions.aspectRatio = xInit + ':' + yInit;
                        }
-                       if ( flexHeight === false ) {
-                               imgSelectOptions.maxHeight = yInit;
+
+                       if ( true === flexHeight ) {
+                               delete imgSelectOptions.minHeight;
+                               imgSelectOptions.maxWidth = realWidth;
                        }
-                       if ( flexWidth === false ) {
-                               imgSelectOptions.maxWidth = xInit;
+
+                       if ( true === flexWidth ) {
+                               delete imgSelectOptions.minWidth;
+                               imgSelectOptions.maxHeight = realHeight;
                        }
 
                        return imgSelectOptions;
                                api.HeaderTool.UploadsList,
                                api.HeaderTool.DefaultsList
                        ]);
+
+                       // Ensure custom-header-crop Ajax requests bootstrap the Customizer to activate the previewed theme.
+                       wp.media.controller.Cropper.prototype.defaults.doCropArgs.wp_customize = 'on';
+                       wp.media.controller.Cropper.prototype.defaults.doCropArgs.theme = api.settings.theme.stylesheet;
                },
 
                /**
 
                                iframe = $( '<iframe />', { 'src': self.previewUrl(), 'title': api.l10n.previewIframeTitle } ).hide();
                                iframe.appendTo( self.container );
-                               iframe.load( function() {
+                               iframe.on( 'load', function() {
                                        self.triedLogin = true;
 
                                        iframe.remove();
 
                        // Limit the URL to internal, front-end links.
                        //
-                       // If the frontend and the admin are served from the same domain, load the
+                       // If the front end and the admin are served from the same domain, load the
                        // preview over ssl if the Customizer is being loaded over ssl. This avoids
-                       // insecure content warnings. This is not attempted if the admin and frontend
-                       // are on different domains to avoid the case where the frontend doesn't have
+                       // insecure content warnings. This is not attempted if the admin and front end
+                       // are on different domains to avoid the case where the front end doesn't have
                        // ssl certs.
 
                        this.add( 'previewUrl', params.previewUrl ).setter( function( to ) {
                        overlay = body.children( '.wp-full-overlay' ),
                        title = $( '#customize-info .panel-title.site-title' ),
                        closeBtn = $( '.customize-controls-close' ),
-                       saveBtn = $( '#save' );
+                       saveBtn = $( '#save' ),
+                       footerActions = $( '#customize-footer-actions' );
 
                // Prevent the form from saving when enter is pressed on an input or select element.
                $('#customize-controls').on( 'keydown', function( e ) {
                                                        value._dirty = false;
                                                } );
 
+                                               api.previewer.send( 'saved', response );
+
                                                api.trigger( 'saved', response );
                                        } );
                                };
                api.bind( 'nonce-refresh', function( nonce ) {
                        $.extend( api.settings.nonce, nonce );
                        $.extend( api.previewer.nonce, nonce );
+                       api.previewer.send( 'nonce-refresh', nonce );
                });
 
                // Create Settings
                });
 
                // Focus the autofocused element
-               _.each( [ 'panel', 'section', 'control' ], function ( type ) {
-                       var instance, id = api.settings.autofocus[ type ];
-                       if ( id && api[ type ]( id ) ) {
-                               instance = api[ type ]( id );
-                               // Wait until the element is embedded in the DOM
-                               instance.deferred.embedded.done( function () {
-                                       // Wait until the preview has activated and so active panels, sections, controls have been set
-                                       api.previewer.deferred.active.done( function () {
+               _.each( [ 'panel', 'section', 'control' ], function( type ) {
+                       var id = api.settings.autofocus[ type ];
+                       if ( ! id ) {
+                               return;
+                       }
+
+                       /*
+                        * Defer focus until:
+                        * 1. The panel, section, or control exists (especially for dynamically-created ones).
+                        * 2. The instance is embedded in the document (and so is focusable).
+                        * 3. The preview has finished loading so that the active states have been set.
+                        */
+                       api[ type ]( id, function( instance ) {
+                               instance.deferred.embedded.done( function() {
+                                       api.previewer.deferred.active.done( function() {
                                                instance.focus();
                                        });
                                });
-                       }
+                       });
                });
 
                /**
                        event.preventDefault();
                });
 
+               // Previewed device bindings.
+               api.previewedDevice = new api.Value();
+
+               // Set the default device.
+               api.bind( 'ready', function() {
+                       _.find( api.settings.previewableDevices, function( value, key ) {
+                               if ( true === value['default'] ) {
+                                       api.previewedDevice.set( key );
+                                       return true;
+                               }
+                       } );
+               } );
+
+               // Set the toggled device.
+               footerActions.find( '.devices button' ).on( 'click', function( event ) {
+                       api.previewedDevice.set( $( event.currentTarget ).data( 'device' ) );
+               });
+
+               // Bind device changes.
+               api.previewedDevice.bind( function( newDevice ) {
+                       var overlay = $( '.wp-full-overlay' ),
+                               devices = '';
+
+                       footerActions.find( '.devices button' )
+                               .removeClass( 'active' )
+                               .attr( 'aria-pressed', false );
+
+                       footerActions.find( '.devices .preview-' + newDevice )
+                               .addClass( 'active' )
+                               .attr( 'aria-pressed', true );
+
+                       $.each( api.settings.previewableDevices, function( device ) {
+                               devices += ' preview-' + device;
+                       } );
+
+                       overlay
+                               .removeClass( devices )
+                               .addClass( 'preview-' + newDevice );
+               } );
+
                // Bind site title display to the corresponding field.
                if ( title.length ) {
-                       $( '#customize-control-blogname input' ).on( 'input', function() {
-                               title.text( this.value );
+                       api( 'blogname', function( setting ) {
+                               var updateTitle = function() {
+                                       title.text( $.trim( setting() ) || api.l10n.untitledBlogName );
+                               };
+                               setting.bind( updateTitle );
+                               updateTitle();
                        } );
                }
 
                        });
                });
 
+               // Focus on the control that is associated with the given setting.
+               api.previewer.bind( 'focus-control-for-setting', function( settingId ) {
+                       var matchedControl;
+                       api.control.each( function( control ) {
+                               var settingIds = _.pluck( control.settings, 'id' );
+                               if ( -1 !== _.indexOf( settingIds, settingId ) ) {
+                                       matchedControl = control;
+                               }
+                       } );
+
+                       if ( matchedControl ) {
+                               matchedControl.focus();
+                       }
+               } );
+
+               // Refresh the preview when it requests.
+               api.previewer.bind( 'refresh', function() {
+                       api.previewer.refresh();
+               });
+
                api.trigger( 'ready' );
 
                // Make sure left column gets focus