WordPress.org

Make WordPress Core

Changeset 41797


Ignore:
Timestamp:
10/09/17 16:03:35 (10 days ago)
Author:
westonruter
Message:

Customize: Eliminate use of customize-loader in core so Customizer is opened consistently in top window.

  • Open the door for future browser history feature in #28536, which is currently not feasible when customize-loader is used.
  • Remove customizer-loader from being used on admin screens for Dashboard, Themes, non-shiny theme install/update.
  • Keep the customize-loader functionality available for plugins, for the time being. It may become deprecated.
  • Ensure return param in customizer links in Themes screen update to reflect search updated by pushState.
  • Persist return when reloading Customizer due to theme switch, autosave restoration, or changeset trashing.
  • Use location.replace() instead of changing location.href when trashing.
  • Hide theme browser while Themes screen is loading when there is a search to prevent flash of unfiltered themes.
  • Use throttling instead of debouncing when searching themes to ensure that screen is updated immediately on page load.
  • Fix encoding and decoding of search param between URL and search field.
  • Add support for dismissing autosaves when closing customize-loader, when it is used by plugins.
  • Skip sending changeset UUID to customize-loader for population in browser location if changeset branching is not enabled.

See #28536.
Fixes #40254.

Location:
trunk/src
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/themes.css

    r41667 r41797  
    77  16.1 - Manage Themes 
    88------------------------------------------------------------------------------*/ 
     9 
     10body.js .theme-browser.search-loading { 
     11    display: none; 
     12} 
    913 
    1014.theme-browser .themes { 
  • trunk/src/wp-admin/includes/class-theme-installer-skin.php

    r41161 r41797  
    6565 
    6666        if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { 
    67             $install_actions['preview'] = '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Live Preview' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Live Preview &#8220;%s&#8221;' ), $name ) . '</span></a>'; 
     67            $customize_url = add_query_arg( 
     68                array( 
     69                    'theme' => urlencode( $stylesheet ), 
     70                    'return' => urlencode( admin_url( 'web' === $this->type ? 'theme-install.php' : 'themes.php' ) ), 
     71                ), 
     72                admin_url( 'customize.php' ) 
     73            ); 
     74            $install_actions['preview'] = '<a href="' . esc_url( $customize_url ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Live Preview' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Live Preview &#8220;%s&#8221;' ), $name ) . '</span></a>'; 
    6875        } 
    6976        $install_actions['activate'] = '<a href="' . esc_url( $activate_link ) . '" class="activatelink"><span aria-hidden="true">' . __( 'Activate' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Activate &#8220;%s&#8221;' ), $name ) . '</span></a>'; 
  • trunk/src/wp-admin/includes/class-theme-upgrader-skin.php

    r41161 r41797  
    5050            $activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet ); 
    5151 
     52            $customize_url = add_query_arg( 
     53                array( 
     54                    'theme' => urlencode( $stylesheet ), 
     55                    'return' => urlencode( admin_url( 'themes.php' ) ), 
     56                ), 
     57                admin_url( 'customize.php' ) 
     58            ); 
    5259            if ( get_stylesheet() == $stylesheet ) { 
    5360                if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { 
    54                     $update_actions['preview']  = '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Customize' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Customize &#8220;%s&#8221;' ), $name ) . '</span></a>'; 
     61                    $update_actions['preview']  = '<a href="' . esc_url( $customize_url ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Customize' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Customize &#8220;%s&#8221;' ), $name ) . '</span></a>'; 
    5562                } 
    5663            } elseif ( current_user_can( 'switch_themes' ) ) { 
    5764                if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { 
    58                     $update_actions['preview'] = '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Live Preview' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Live Preview &#8220;%s&#8221;' ), $name ) . '</span></a>'; 
     65                    $update_actions['preview'] = '<a href="' . esc_url( $customize_url ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Live Preview' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Live Preview &#8220;%s&#8221;' ), $name ) . '</span></a>'; 
    5966                } 
    6067                $update_actions['activate'] = '<a href="' . esc_url( $activate_link ) . '" class="activatelink"><span aria-hidden="true">' . __( 'Activate' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Activate &#8220;%s&#8221;' ), $name ) . '</span></a>'; 
  • trunk/src/wp-admin/index.php

    r40776 r41797  
    1717wp_enqueue_script( 'dashboard' ); 
    1818 
    19 if ( current_user_can( 'edit_theme_options' ) ) 
    20     wp_enqueue_script( 'customize-loader' ); 
    2119if ( current_user_can( 'install_plugins' ) ) { 
    2220    wp_enqueue_script( 'plugin-install' ); 
  • trunk/src/wp-admin/js/customize-controls.js

    r41788 r41797  
    107107         * @since 4.9.0 
    108108         * 
    109          * @param {string|wp.customize.Notification} - Notification object to add. Alternatively code may be supplied, and in that case the second notificationObject argument must be supplied. 
     109         * @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. 
    110110         * @param {wp.customize.Notification} [notificationObject] - Notification to add when first argument is the code string. 
    111111         * @returns {wp.customize.Notification} Added notification (or existing instance if it was already added). 
     
    30153015                { 
    30163016                    theme: themeId, 
    3017                     changeset_uuid: api.settings.changeset.uuid 
     3017                    changeset_uuid: api.settings.changeset.uuid, 
     3018                    'return': api.settings.url['return'] 
    30183019                } 
    30193020            ); 
     
    30453046                    deferred.resolve(); 
    30463047                    $( window ).off( 'beforeunload.customize-confirm' ); 
    3047                     window.location.href = urlParser.href; // @todo Use location.replace()? 
     3048                    location.replace( urlParser.href ); 
    30483049                } ); 
    30493050                request.fail( function() { 
     
    69596960                            api.settings.changeset.uuid = response.next_changeset_uuid; 
    69606961                            api.state( 'changesetStatus' ).set( '' ); 
    6961                             parent.send( 'changeset-uuid', api.settings.changeset.uuid ); 
     6962                            if ( api.settings.changeset.branching ) { 
     6963                                parent.send( 'changeset-uuid', api.settings.changeset.uuid ); 
     6964                            } 
    69626965                            api.previewer.send( 'changeset-uuid', api.settings.changeset.uuid ); 
    69636966                        } 
     
    69906993                            api.state( 'changesetStatus' ).set( '' ); 
    69916994                            api.settings.changeset.uuid = response.next_changeset_uuid; 
    6992                             parent.send( 'changeset-uuid', api.settings.changeset.uuid ); 
     6995                            if ( api.settings.changeset.branching ) { 
     6996                                parent.send( 'changeset-uuid', api.settings.changeset.uuid ); 
     6997                            } 
    69936998                        } 
    69946999 
     
    70667071                    queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) ); 
    70677072                    delete queryParams.changeset_uuid; 
     7073                    queryParams['return'] = api.settings.url['return']; 
    70687074                    urlParser.search = $.param( queryParams ); 
    70697075                    location.replace( urlParser.href ); 
     
    74197425                    queryParams.customize_autosaved = 'on'; 
    74207426                } 
     7427                queryParams['return'] = api.settings.url['return']; 
    74217428                urlParser.search = $.param( queryParams ); 
    74227429                return urlParser.href; 
     
    79167923            api.bind( 'change', startPromptingBeforeUnload ); 
    79177924 
    7918             closeBtn.on( 'click.customize-controls-close', function( event ) { 
     7925            function requestClose() { 
    79197926                var clearedToClose = $.Deferred(); 
    7920                 event.preventDefault(); 
    7921  
    7922                 /* 
    7923                  * The isInsideIframe condition is because Customizer is not able to use a confirm() 
    7924                  * since customize-loader.js will also use one. So autosave restorations are disabled 
    7925                  * when customize-loader.js is used. 
    7926                  */ 
    7927                 if ( isInsideIframe || isCleanState() ) { 
     7927                if ( isCleanState() ) { 
    79287928                    clearedToClose.resolve(); 
    79297929                } else if ( confirm( api.l10n.saveAlert ) ) { 
     
    79557955                    clearedToClose.reject(); 
    79567956                } 
    7957  
    7958                 clearedToClose.done( function() { 
    7959                     $( window ).off( 'beforeunload.customize-confirm' ); 
    7960                     if ( isInsideIframe ) { 
    7961                         parent.send( 'close' ); 
    7962                     } else { 
     7957                return clearedToClose.promise(); 
     7958            } 
     7959 
     7960            parent.bind( 'confirm-close', function() { 
     7961                requestClose().done( function() { 
     7962                    parent.send( 'confirmed-close', true ); 
     7963                } ).fail( function() { 
     7964                    parent.send( 'confirmed-close', false ); 
     7965                } ); 
     7966            } ); 
     7967 
     7968            closeBtn.on( 'click.customize-controls-close', function( event ) { 
     7969                event.preventDefault(); 
     7970                if ( isInsideIframe ) { 
     7971                    parent.send( 'close' ); // See confirm-close logic above. 
     7972                } else { 
     7973                    requestClose().done( function() { 
     7974                        $( window ).off( 'beforeunload.customize-confirm' ); 
    79637975                        window.location.href = closeBtn.prop( 'href' ); 
    7964                     } 
    7965                 } ); 
     7976                    } ); 
     7977                } 
    79667978            }); 
    79677979        })(); 
     
    79797991        }); 
    79807992 
    7981         parent.send( 'changeset-uuid', api.settings.changeset.uuid ); 
     7993        if ( api.settings.changeset.branching ) { 
     7994            parent.send( 'changeset-uuid', api.settings.changeset.uuid ); 
     7995        } 
    79827996 
    79837997        // Initialize the connection with the parent frame. 
  • trunk/src/wp-admin/js/theme.js

    r41683 r41797  
    7777        // Render search form. 
    7878        this.search(); 
     79 
     80        this.$el.removeClass( 'search-loading' ); 
    7981 
    8082        // Render and append 
     
    13461348        } 
    13471349 
    1348         /** 
    1349          * Since doSearch is debounced, it will only run when user input comes to a rest 
    1350          */ 
     1350        // Note that doSearch is throttled. 
    13511351        this.doSearch( event ); 
    13521352    }, 
    13531353 
    13541354    // Runs a search on the theme collection. 
    1355     doSearch: _.debounce( function( event ) { 
     1355    doSearch: _.throttle( function( event ) { 
    13561356        var options = {}; 
    13571357 
    1358         this.collection.doSearch( event.target.value ); 
     1358        this.collection.doSearch( event.target.value.replace( /\+/g, ' ' ) ); 
    13591359 
    13601360        // if search is initiated and key is not return 
     
    13771377 
    13781378        if ( event.target.value ) { 
    1379             url = themes.router.baseUrl( themes.router.searchPath + event.target.value ); 
     1379            url = themes.router.baseUrl( themes.router.searchPath + encodeURIComponent( event.target.value ) ); 
    13801380        } 
    13811381 
     
    13851385    } 
    13861386}); 
     1387 
     1388/** 
     1389 * Navigate router. 
     1390 * 
     1391 * @since 4.9.0 
     1392 * 
     1393 * @param {string} url - URL to navigate to. 
     1394 * @param {object} state - State. 
     1395 * @returns {void} 
     1396 */ 
     1397function navigateRouter( url, state ) { 
     1398    var router = this; 
     1399    if ( Backbone.history._hasPushState ) { 
     1400        Backbone.Router.prototype.navigate.call( router, url, state ); 
     1401    } 
     1402} 
    13871403 
    13881404// Sets up the routes events for relevant url queries 
     
    14061422 
    14071423    search: function( query ) { 
    1408         $( '.wp-filter-search' ).val( query ); 
     1424        $( '.wp-filter-search' ).val( query.replace( /\+/g, ' ' ) ); 
    14091425    }, 
    14101426 
     
    14131429    }, 
    14141430 
    1415     navigate: function() { 
    1416         if ( Backbone.history._hasPushState ) { 
    1417             Backbone.Router.prototype.navigate.apply( this, arguments ); 
    1418         } 
    1419     } 
     1431    navigate: navigateRouter 
    14201432 
    14211433}); 
     
    15091521    }, 
    15101522 
    1511     doSearch: _.debounce( function( value ) { 
     1523    doSearch: _.throttle( function( value ) { 
    15121524        var request = {}; 
    15131525 
     
    15521564 
    15531565        // Set route 
    1554         themes.router.navigate( themes.router.baseUrl( themes.router.searchPath + value ), { replace: true } ); 
     1566        themes.router.navigate( themes.router.baseUrl( themes.router.searchPath + encodeURIComponent( value ) ), { replace: true } ); 
    15551567    }, 500 ) 
    15561568}); 
     
    18881900 
    18891901    search: function( query ) { 
    1890         $( '.wp-filter-search' ).val( query ); 
    1891     }, 
    1892  
    1893     navigate: function() { 
    1894         if ( Backbone.history._hasPushState ) { 
    1895             Backbone.Router.prototype.navigate.apply( this, arguments ); 
    1896         } 
    1897     } 
     1902        $( '.wp-filter-search' ).val( query.replace( /\+/g, ' ' ) ); 
     1903    }, 
     1904 
     1905    navigate: navigateRouter 
    18981906}); 
    18991907 
     
    20032011        themes.Run.init(); 
    20042012    } 
     2013 
     2014    // Update the return param just in time. 
     2015    $( document.body ).on( 'click', '.load-customize', function() { 
     2016        var link = $( this ), urlParser = document.createElement( 'a' ); 
     2017        urlParser.href = link.prop( 'href' ); 
     2018        urlParser.search = $.param( _.extend( 
     2019            wp.customize.utils.parseQueryString( urlParser.search.substr( 1 ) ), 
     2020            { 
     2021                'return': window.location.href 
     2022            } 
     2023        ) ); 
     2024        link.prop( 'href', urlParser.href ); 
     2025    }); 
    20052026 
    20062027    $( '.broken-themes .delete-theme' ).on( 'click', function() { 
  • trunk/src/wp-admin/themes.php

    r41658 r41797  
    147147wp_enqueue_script( 'theme' ); 
    148148wp_enqueue_script( 'updates' ); 
    149 wp_enqueue_script( 'customize-loader' ); 
    150149 
    151150require_once( ABSPATH . 'wp-admin/admin-header.php' ); 
     
    154153<div class="wrap"> 
    155154    <h1 class="wp-heading-inline"><?php esc_html_e( 'Themes' ); ?> 
    156         <span class="title-count theme-count"><?php echo count( $themes ); ?></span> 
     155        <span class="title-count theme-count"><?php echo ! empty( $_GET['search'] ) ? __( '&hellip;' ) : count( $themes ); ?></span> 
    157156    </h1> 
    158157 
     
    235234?> 
    236235 
    237 <div class="theme-browser"> 
     236<?php 
     237$class_name = 'theme-browser'; 
     238if ( ! empty( $_GET['search'] ) ) { 
     239    $class_name .= ' search-loading'; 
     240} 
     241?> 
     242<div class="<?php echo esc_attr( $class_name ); ?>"> 
    238243    <div class="themes wp-clearfix"> 
    239244 
  • trunk/src/wp-admin/update.php

    r41289 r41797  
    174174        check_admin_referer('upgrade-theme_' . $theme); 
    175175 
    176         wp_enqueue_script( 'customize-loader' ); 
    177176        wp_enqueue_script( 'updates' ); 
    178177 
     
    224223        $api = themes_api('theme_information', array('slug' => $theme, 'fields' => array('sections' => false, 'tags' => false) ) ); //Save on a bit of bandwidth. 
    225224 
    226         if ( is_wp_error($api) ) 
    227             wp_die($api); 
    228  
    229         wp_enqueue_script( 'customize-loader' ); 
     225        if ( is_wp_error( $api ) ) { 
     226            wp_die( $api ); 
     227        } 
    230228 
    231229        $title = __('Install Themes'); 
     
    253251 
    254252        $file_upload = new File_Upload_Upgrader('themezip', 'package'); 
    255  
    256         wp_enqueue_script( 'customize-loader' ); 
    257253 
    258254        $title = __('Upload Theme'); 
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r41793 r41797  
    42374237            'url'      => array( 
    42384238                'preview'       => esc_url_raw( $this->get_preview_url() ), 
     4239                'return'        => esc_url_raw( $this->get_return_url() ), 
    42394240                'parent'        => esc_url_raw( admin_url() ), 
    42404241                'activated'     => esc_url_raw( home_url( '/' ) ), 
  • trunk/src/wp-includes/js/customize-loader.js

    r41351 r41797  
    1 /* global _wpCustomizeLoaderSettings, confirm */ 
     1/* global _wpCustomizeLoaderSettings */ 
    22/** 
    33 * Expose a public API that allows the customizer to be 
     
    209209         */ 
    210210        close: function() { 
    211             if ( ! this.active ) { 
     211            var self = this, onConfirmClose; 
     212            if ( ! self.active ) { 
    212213                return; 
    213214            } 
    214215 
    215             // Display AYS dialog if Customizer is dirty 
    216             if ( ! this.saved() && ! confirm( Loader.settings.l10n.saveAlert ) ) { 
    217                 // Go forward since Customizer is exited by history.back() 
    218                 history.forward(); 
    219                 return; 
    220             } 
    221  
    222             this.active = false; 
    223  
    224             this.trigger( 'close' ); 
    225  
    226             // Restore document title prior to opening the Live Preview 
    227             if ( this.originalDocumentTitle ) { 
    228                 document.title = this.originalDocumentTitle; 
    229             } 
     216            onConfirmClose = function( confirmed ) { 
     217                if ( confirmed ) { 
     218                    self.active = false; 
     219                    self.trigger( 'close' ); 
     220 
     221                    // Restore document title prior to opening the Live Preview 
     222                    if ( self.originalDocumentTitle ) { 
     223                        document.title = self.originalDocumentTitle; 
     224                    } 
     225                } else { 
     226 
     227                    // Go forward since Customizer is exited by history.back() 
     228                    history.forward(); 
     229                } 
     230                self.messenger.unbind( 'confirmed-close', onConfirmClose ); 
     231            }; 
     232            self.messenger.bind( 'confirmed-close', onConfirmClose ); 
     233 
     234            Loader.messenger.send( 'confirm-close' ); 
    230235        }, 
    231236 
  • trunk/src/wp-includes/script-loader.php

    r41791 r41797  
    726726        $scripts->add( 'custom-html-widgets', "/wp-admin/js/widgets/custom-html-widgets$suffix.js", array( 'code-editor', 'jquery', 'backbone', 'wp-util', 'jquery-ui-core', 'wp-a11y' ) ); 
    727727 
    728         $scripts->add( 'theme', "/wp-admin/js/theme$suffix.js", array( 'wp-backbone', 'wp-a11y' ), false, 1 ); 
     728        $scripts->add( 'theme', "/wp-admin/js/theme$suffix.js", array( 'wp-backbone', 'wp-a11y', 'customize-base' ), false, 1 ); 
    729729 
    730730        $scripts->add( 'inline-edit-post', "/wp-admin/js/inline-edit-post$suffix.js", array( 'jquery', 'tags-suggest', 'wp-a11y' ), false, 1 ); 
Note: See TracChangeset for help on using the changeset viewer.