Make WordPress Core

Ticket #32814: reboot.diff

File reboot.diff, 13.3 KB (added by wonderboymusic, 10 years ago)
  • src/wp-includes/class-wp-customize-nav-menus.php

     
    848848                                'active'     => $this->manager->is_theme_active(),
    849849                        ),
    850850                        'previewCustomizeNonce' => wp_create_nonce( 'preview-customize_' . $this->manager->get_stylesheet() ),
    851                         'navMenuInstanceArgs'  => $this->preview_nav_menu_instance_args,
     851                        'args' => $this->preview_nav_menu_instance_args,
    852852                );
    853853
    854854                if ( ! empty( $_SERVER['REQUEST_URI'] ) ) {
     
    855855                        $exports['requestUri'] = esc_url_raw( home_url( wp_unslash( $_SERVER['REQUEST_URI'] ) ) );
    856856                }
    857857
    858                 printf( '<script>var _wpCustomizePreviewNavMenusExports = %s;</script>', wp_json_encode( $exports ) );
     858                printf( '<script>var _wpCustomizePreviewNavMenus = %s;</script>', wp_json_encode( $exports ) );
    859859        }
    860860
    861861        /**
  • src/wp-includes/js/customize-preview-nav-menus.js

     
    1 /*global jQuery, JSON, _wpCustomizePreviewNavMenusExports, _ */
     1/*global jQuery, JSON, _wpCustomizePreviewNavMenus, _ */
    22
    3 wp.customize.menusPreview = ( function( $, api ) {
     3( function( $, api ) {
    44        'use strict';
    5         var self;
    65
    7         self = {
    8                 renderQueryVar: null,
    9                 renderNonceValue: null,
    10                 renderNoncePostKey: null,
    11                 previewCustomizeNonce: null,
    12                 previewReady: $.Deferred(),
    13                 requestUri: '/',
    14                 theme: {
    15                         active: false,
    16                         stylesheet: ''
     6        var utils,
     7                settings = {
     8                        renderQueryVar: null,
     9                        renderNonceValue: null,
     10                        renderNoncePostKey: null,
     11                        previewCustomizeNonce: null,
     12                        requestUri: '/',
     13                        theme: {
     14                                active: false,
     15                                stylesheet: ''
     16                        },
     17                        args: {}
    1718                },
    18                 navMenuInstanceArgs: {},
    19                 refreshDebounceDelay: 200
    20         };
    2119
    22         api.bind( 'preview-ready', function() {
    23                 self.previewReady.resolve();
    24         } );
    25         self.previewReady.done( function() {
    26                 self.init();
    27         } );
     20                debouncedCalls = {},
     21                refreshDelay = 200,
     22                utils;
    2823
    29         /**
    30          * Bootstrap functionality.
    31          */
    32         self.init = function() {
    33                 var self = this;
     24        utils = api.NavMenusCustomizerPreview = {
     25               
     26                refreshDebounced: function( instance ) {
     27                        if ( debouncedCalls[ instance ] ) {
     28                                window.clearTimeout( debouncedCalls[ instance ] );
     29                        }
     30                        debouncedCalls[ instance ] = window.setTimeout( _.bind( function() {
     31                                this.refreshMenuInstance( instance );
     32                        }, this ), refreshDelay );
     33                },
    3434
    35                 if ( 'undefined' !== typeof _wpCustomizePreviewNavMenusExports ) {
    36                         $.extend( self, _wpCustomizePreviewNavMenusExports );
    37                 }
     35                /**
     36                 * Update a given menu rendered in the preview.
     37                 *
     38                 * @param {int} menuId
     39                 */
     40                refreshMenu : function( menuId ) {
     41                        var locations = [];
    3842
    39                 self.previewReady.done( function() {
    40                         api.each( function( setting, id ) {
    41                                 setting.id = id;
    42                                 self.bindListener( setting );
    43                         } );
     43                        api.each(function( setting, id ) {
     44                                var matches = id.match( /^nav_menu_locations\[(.+?)]/ );
     45                                if ( matches && menuId === setting() ) {
     46                                        locations.push( matches[1] );
     47                                }
     48                        });
    4449
    45                         api.preview.bind( 'setting', function( args ) {
    46                                 var id, value, setting;
    47                                 args = args.slice();
    48                                 id = args.shift();
    49                                 value = args.shift();
    50                                 if ( ! api.has( id ) ) {
    51                                         // Currently customize-preview.js is not creating settings for dynamically-created settings in the pane; so we have to do it
    52                                         setting = api.create( id, value ); // @todo This should be in core
    53                                         setting.id = id;
    54                                         if ( self.bindListener( setting ) ) {
    55                                                 setting.callbacks.fireWith( setting, [ setting(), setting() ] );
    56                                         }
     50                        _.each( settings.args, function( args, instance ) {
     51                                if ( menuId === args.menu || -1 !== _.indexOf( locations, args.theme_location ) ) {
     52                                        this.refreshDebounced( instance );
    5753                                }
    58                         } );
    59                 } );
    60         };
     54                        }, this );
     55                },
    6156
    62         /**
    63          *
    64          * @param {wp.customize.Value} setting
    65          * @returns {boolean} Whether the setting was bound.
    66          */
    67         self.bindListener = function( setting ) {
    68                 var matches, themeLocation;
     57                refreshMenuLocation : function( location ) {
     58                        var found = false;
    6959
    70                 matches = setting.id.match( /^nav_menu\[(-?\d+)]$/ );
    71                 if ( matches ) {
    72                         setting.navMenuId = parseInt( matches[1], 10 );
    73                         setting.bind( self.onChangeNavMenuSetting );
    74                         return true;
    75                 }
     60                        _.each( settings.args, function( args, instance ) {
     61                                if ( location === args.theme_location ) {
     62                                        this.refreshDebounced( instance );
     63                                        found = true;
     64                                }
     65                        }, this );
    7666
    77                 matches = setting.id.match( /^nav_menu_item\[(-?\d+)]$/ );
    78                 if ( matches ) {
    79                         setting.navMenuItemId = parseInt( matches[1], 10 );
    80                         setting.bind( self.onChangeNavMenuItemSetting );
    81                         return true;
    82                 }
     67                        if ( ! found ) {
     68                                api.preview.send( 'refresh' );
     69                        }
     70                },
    8371
    84                 matches = setting.id.match( /^nav_menu_locations\[(.+?)]/ );
    85                 if ( matches ) {
    86                         themeLocation = matches[1];
    87                         setting.bind( function() {
    88                                 self.refreshMenuLocation( themeLocation );
     72                /**
     73                 * Update a specific instance of a given menu on the page.
     74                 *
     75                 * @param {int} instance
     76                 */
     77                refreshMenuInstance : function( instance ) {
     78                        var data, customized, container, wpNavArgs;
     79
     80                        if ( ! settings.args[ instance ] ) {
     81                                throw new Error( 'unknown_instance_number' );
     82                        }
     83
     84                        container = $( '#partial-refresh-menu-container-' + instance );
     85
     86                        if ( ! settings.args[ instance ].can_partial_refresh || 0 === container.length ) {
     87                                api.preview.send( 'refresh' );
     88                                return;
     89                        }
     90
     91                        data = {
     92                                nonce: settings.previewCustomizeNonce,
     93                                wp_customize: 'on'
     94                        };
     95                        if ( ! settings.theme.active ) {
     96                                data.theme = settings.theme.stylesheet;
     97                        }
     98                        data[ settings.renderQueryVar ] = '1';
     99
     100                        customized = {};
     101                        api.each( function( setting, id ) {
     102                                // @todo We need to limit this to just the menu items that are associated with this menu/location.
     103                                if ( /^(nav_menu|nav_menu_locations)/.test( id ) ) {
     104                                        customized[ id ] = setting.get();
     105                                }
    89106                        } );
    90                         return true;
    91                 }
     107                        data.customized = JSON.stringify( customized );
     108                        data[ settings.renderNoncePostKey ] = settings.renderNonceValue;
    92109
    93                 return false;
    94         };
     110                        wpNavArgs = $.extend( {}, settings.args[ instance ] );
     111                        data.wp_nav_menu_args_hash = wpNavArgs.args_hash;
     112                        delete wpNavArgs.args_hash;
     113                        data.wp_nav_menu_args = JSON.stringify( wpNavArgs );
    95114
    96         /**
    97          * Handle changing of a nav_menu setting.
    98          *
    99          * @this {wp.customize.Setting}
    100          */
    101         self.onChangeNavMenuSetting = function() {
    102                 var setting = this;
    103                 if ( ! setting.navMenuId ) {
    104                         throw new Error( 'Expected navMenuId property to be set.' );
    105                 }
    106                 self.refreshMenu( setting.navMenuId );
    107         };
     115                        container.addClass( 'customize-partial-refreshing' );
    108116
    109         /**
    110          * Handle changing of a nav_menu_item setting.
    111          *
    112          * @this {wp.customize.Setting}
    113          * @param {object} to
    114          * @param {object} from
    115          */
    116         self.onChangeNavMenuItemSetting = function( to, from ) {
    117                 if ( from && from.nav_menu_term_id && ( ! to || from.nav_menu_term_id !== to.nav_menu_term_id ) ) {
    118                         self.refreshMenu( from.nav_menu_term_id );
    119                 }
    120                 if ( to && to.nav_menu_term_id ) {
    121                         self.refreshMenu( to.nav_menu_term_id );
    122                 }
    123         };
     117                        wp.ajax.send( null, {
     118                                data: data,
     119                                url: settings.requestUri
     120                        } )
     121                                .done( function( data ) {
     122                                        var eventParam;
     123                                        container.empty().append( $( data ) );
     124                                        eventParam = {
     125                                                instanceNumber: instance,
     126                                                wpNavArgs: wpNavArgs
     127                                        };
     128                                        $( document ).trigger( 'customize-preview-menu-refreshed', [ eventParam ] );
     129                                } )
     130                                .fail( function() {
     131                                        // @todo provide some indication for why
     132                                } )
     133                                .always( function() {
     134                                        container.removeClass( 'customize-partial-refreshing' );
     135                                } );
     136                },
    124137
    125         /**
    126          * Update a given menu rendered in the preview.
    127          *
    128          * @param {int} menuId
    129         */
    130         self.refreshMenu = function( menuId ) {
    131                 var self = this, assignedLocations = [];
     138                /**
     139                 *
     140                 * @param {wp.customize.Value} setting
     141                 * @returns {boolean} Whether the setting was bound.
     142                */
     143                bindListener : function( setting ) {
     144                        var matches, themeLocation;
    132145
    133                 api.each(function( setting, id ) {
    134                         var matches = id.match( /^nav_menu_locations\[(.+?)]/ );
    135                         if ( matches && menuId === setting() ) {
    136                                 assignedLocations.push( matches[1] );
     146                        matches = setting.id.match( /^nav_menu\[(-?\d+)]$/ );
     147                        if ( matches ) {
     148                                setting.navMenuId = parseInt( matches[1], 10 );
     149                                setting.bind( function() {
     150                                        if ( ! this.navMenuId ) {
     151                                                throw new Error( 'Expected navMenuId property to be set.' );
     152                                        }
     153                                        utils.refreshMenu( this.navMenuId );
     154                                } );
     155                                return true;
    137156                        }
    138                 });
    139157
    140                 _.each( self.navMenuInstanceArgs, function( navMenuArgs, instanceNumber ) {
    141                         if ( menuId === navMenuArgs.menu || -1 !== _.indexOf( assignedLocations, navMenuArgs.theme_location ) ) {
    142                                 self.refreshMenuInstanceDebounced( instanceNumber );
     158                        matches = setting.id.match( /^nav_menu_item\[(-?\d+)]$/ );
     159                        if ( matches ) {
     160                                setting.navMenuItemId = parseInt( matches[1], 10 );
     161                                setting.bind( function( to, from ) {
     162                                        if ( from && from.nav_menu_term_id &&
     163                                                ( ! to || from.nav_menu_term_id !== to.nav_menu_term_id ) ) {
     164                                                utils.refreshMenu( from.nav_menu_term_id );
     165                                        }
     166                                        if ( to && to.nav_menu_term_id ) {
     167                                                utils.refreshMenu( to.nav_menu_term_id );
     168                                        }
     169                                } );
     170                                return true;
    143171                        }
    144                 } );
    145         };
    146172
    147         self.refreshMenuLocation = function( location ) {
    148                 var foundInstance = false;
    149                 _.each( self.navMenuInstanceArgs, function( navMenuArgs, instanceNumber ) {
    150                         if ( location === navMenuArgs.theme_location ) {
    151                                 self.refreshMenuInstanceDebounced( instanceNumber );
    152                                 foundInstance = true;
     173                        matches = setting.id.match( /^nav_menu_locations\[(.+?)]/ );
     174                        if ( matches ) {
     175                                themeLocation = matches[1];
     176                                setting.bind( function() {
     177                                        utils.refreshMenuLocation( themeLocation );
     178                                } );
     179                                return true;
    153180                        }
    154                 } );
    155                 if ( ! foundInstance ) {
    156                         api.preview.send( 'refresh' );
     181
     182                        return false;
    157183                }
    158184        };
    159185
    160         /**
    161          * Update a specific instance of a given menu on the page.
    162          *
    163          * @param {int} instanceNumber
    164          */
    165         self.refreshMenuInstance = function( instanceNumber ) {
    166                 var self = this, data, customized, container, request, wpNavArgs, instance;
    167 
    168                 if ( ! self.navMenuInstanceArgs[ instanceNumber ] ) {
    169                         throw new Error( 'unknown_instance_number' );
     186        api.bind( 'preview-ready', function() {
     187                if ( 'undefined' !== typeof _wpCustomizePreviewNavMenus ) {
     188                        $.extend( settings, _wpCustomizePreviewNavMenus );
    170189                }
    171                 instance = self.navMenuInstanceArgs[ instanceNumber ];
    172190
    173                 container = $( '#partial-refresh-menu-container-' + String( instanceNumber ) );
    174 
    175                 if ( ! instance.can_partial_refresh || 0 === container.length ) {
    176                         api.preview.send( 'refresh' );
    177                         return;
    178                 }
    179 
    180                 data = {
    181                         nonce: self.previewCustomizeNonce, // for Customize Preview
    182                         wp_customize: 'on'
    183                 };
    184                 if ( ! self.theme.active ) {
    185                         data.theme = self.theme.stylesheet;
    186                 }
    187                 data[ self.renderQueryVar ] = '1';
    188                 customized = {};
    189191                api.each( function( setting, id ) {
    190                         // @todo We need to limit this to just the menu items that are associated with this menu/location.
    191                         if ( /^(nav_menu|nav_menu_locations)/.test( id ) ) {
    192                                 customized[ id ] = setting.get();
    193                         }
     192                        setting.id = id;
     193                        utils.bindListener( setting );
    194194                } );
    195                 data.customized = JSON.stringify( customized );
    196                 data[ self.renderNoncePostKey ] = self.renderNonceValue;
    197195
    198                 wpNavArgs = $.extend( {}, instance );
    199                 data.wp_nav_menu_args_hash = wpNavArgs.args_hash;
    200                 delete wpNavArgs.args_hash;
    201                 data.wp_nav_menu_args = JSON.stringify( wpNavArgs );
    202 
    203                 container.addClass( 'customize-partial-refreshing' );
    204 
    205                 request = wp.ajax.send( null, {
    206                         data: data,
    207                         url: self.requestUri
     196                api.preview.bind( 'setting', function( args ) {
     197                        var id, value, setting;
     198                        args = args.slice();
     199                        id = args.shift();
     200                        value = args.shift();
     201                        if ( ! api.has( id ) ) {
     202                                // Currently customize-preview.js is not creating settings for dynamically-created settings in the pane; so we have to do it
     203                                setting = api.create( id, value ); // @todo This should be in core
     204                                setting.id = id;
     205                                if ( utils.bindListener( setting ) ) {
     206                                        setting.callbacks.fireWith( setting, [ setting(), setting() ] );
     207                                }
     208                        }
    208209                } );
    209                 request.done( function( data ) {
    210                         var eventParam;
    211                         container.empty().append( $( data ) );
    212                         eventParam = {
    213                                 instanceNumber: instanceNumber,
    214                                 wpNavArgs: wpNavArgs
    215                         };
    216                         $( document ).trigger( 'customize-preview-menu-refreshed', [ eventParam ] );
    217                 } );
    218                 request.fail( function() {
    219                         // @todo provide some indication for why
    220                 } );
    221                 request.always( function() {
    222                         container.removeClass( 'customize-partial-refreshing' );
    223                 } );
    224         };
     210        } );
    225211
    226         self.currentRefreshMenuInstanceDebouncedCalls = {};
    227 
    228         self.refreshMenuInstanceDebounced = function( instanceNumber ) {
    229                 if ( self.currentRefreshMenuInstanceDebouncedCalls[ instanceNumber ] ) {
    230                         clearTimeout( self.currentRefreshMenuInstanceDebouncedCalls[ instanceNumber ] );
    231                 }
    232                 self.currentRefreshMenuInstanceDebouncedCalls[ instanceNumber ] = setTimeout(
    233                         function() {
    234                                 self.refreshMenuInstance( instanceNumber );
    235                         },
    236                         self.refreshDebounceDelay
    237                 );
    238         };
    239 
    240         return self;
    241 
    242212}( jQuery, wp.customize ) );