X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/febc815b2c9d85be5717da9e8d164bd2daa97e31..16e7b37c7914d753890c1a05a9335f3b43751eb8:/wp-includes/js/customize-preview-nav-menus.js diff --git a/wp-includes/js/customize-preview-nav-menus.js b/wp-includes/js/customize-preview-nav-menus.js index bd42f5e0..27c52510 100644 --- a/wp-includes/js/customize-preview-nav-menus.js +++ b/wp-includes/js/customize-preview-nav-menus.js @@ -15,7 +15,19 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * Initialize nav menus preview. */ self.init = function() { - var self = this; + var self = this, synced = false; + + /* + * Keep track of whether we synced to determine whether or not bindSettingListener + * should also initially fire the listener. This initial firing needs to wait until + * after all of the settings have been synced from the pane in order to prevent + * an infinite selective fallback-refresh. Note that this sync handler will be + * added after the sync handler in customize-preview.js, so it will be triggered + * after all of the settings are added. + */ + api.preview.bind( 'sync', function() { + synced = true; + } ); if ( api.selectiveRefresh ) { // Listen for changes to settings related to nav menus. @@ -23,7 +35,17 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( self.bindSettingListener( setting ); } ); api.bind( 'add', function( setting ) { - self.bindSettingListener( setting, { fire: true } ); + + /* + * Handle case where an invalid nav menu item (one for which its associated object has been deleted) + * is synced from the controls into the preview. Since invalid nav menu items are filtered out from + * being exported to the frontend by the _is_valid_nav_menu_item filter in wp_get_nav_menu_items(), + * the customizer controls will have a nav_menu_item setting where the preview will have none, and + * this can trigger an infinite fallback refresh when the nav menu item lacks any valid items. + */ + if ( setting.get() && ! setting.get()._invalid ) { + self.bindSettingListener( setting, { fire: synced } ); + } } ); api.bind( 'remove', function( setting ) { self.unbindSettingListener( setting ); @@ -106,7 +128,7 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( * @returns {boolean} */ isRelatedSetting: function( setting, newValue, oldValue ) { - var partial = this, navMenuLocationSetting, navMenuId, isNavMenuItemSetting; + var partial = this, navMenuLocationSetting, navMenuId, isNavMenuItemSetting, _newValue, _oldValue, urlParser; if ( _.isString( setting ) ) { setting = api( setting ); } @@ -123,9 +145,29 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( */ isNavMenuItemSetting = /^nav_menu_item\[/.test( setting.id ); if ( isNavMenuItemSetting && _.isObject( newValue ) && _.isObject( oldValue ) ) { - delete newValue.type_label; - delete oldValue.type_label; - if ( _.isEqual( oldValue, newValue ) ) { + _newValue = _.clone( newValue ); + _oldValue = _.clone( oldValue ); + delete _newValue.type_label; + delete _oldValue.type_label; + + // Normalize URL scheme when parent frame is HTTPS to prevent selective refresh upon initial page load. + if ( 'https' === api.preview.scheme.get() ) { + urlParser = document.createElement( 'a' ); + urlParser.href = _newValue.url; + urlParser.protocol = 'https:'; + _newValue.url = urlParser.href; + urlParser.href = _oldValue.url; + urlParser.protocol = 'https:'; + _oldValue.url = urlParser.href; + } + + // Prevent original_title differences from causing refreshes if title is present. + if ( newValue.title ) { + delete _oldValue.original_title; + delete _newValue.original_title; + } + + if ( _.isEqual( _oldValue, _newValue ) ) { return false; } } @@ -365,6 +407,11 @@ wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( self.highlightControls = function() { var selector = '.menu-item'; + // Skip adding highlights if not in the customizer preview iframe. + if ( ! api.settings.channel ) { + return; + } + // Focus on the menu item control when shift+clicking the menu item. $( document ).on( 'click', selector, function( e ) { var navMenuItemParts;