Uname: Linux webm005.cluster107.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64
User: 6036 (villadal)
Group: 100 (users)
Disabled functions: NONE
Safe mode: On[ PHPinfo ]
//home/villadal/www///wp-includes2/js      ( Reset | Go to )
File Name: customize-preview-nav-menus.js
Edit
/**
 * @output wp-includes/js/customize-preview-nav-menus.js
 */

/* global _wpCustomizePreviewNavMenusExports */

/** @namespace wp.customize.navMenusPreview */
wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( $, _, wp, api ) {
    'use strict';

    var self = {
        data: {
            navMenuInstanceArgs: {}
        }
    };
    if ( 'undefined' !== typeof _wpCustomizePreviewNavMenusExports ) {
        _.extend( self.data, _wpCustomizePreviewNavMenusExports );
    }

    /**
     * Initialize nav menus preview.
     */
    self.init = function() {
        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.
            api.each( function( setting ) {
                self.bindSettingListener( setting );
            } );
            api.bind( 'add', function( setting ) {

                /*
                 * 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 );
            } );

            /*
             * Ensure that wp_nav_menu() instances nested inside of other partials
             * will be recognized as being present on the page.
             */
            api.selectiveRefresh.bind( 'render-partials-response', function( response ) {
                if ( response.nav_menu_instance_args ) {
                    _.extend( self.data.navMenuInstanceArgs, response.nav_menu_instance_args );
                }
            } );
        }

        api.preview.bind( 'active', function() {
            self.highlightControls();
        } );
    };

    if ( api.selectiveRefresh ) {

        /**
         * Partial representing an invocation of wp_nav_menu().
         *
         * @memberOf wp.customize.navMenusPreview
         * @alias wp.customize.navMenusPreview.NavMenuInstancePartial
         *
         * @class
         * @augments wp.customize.selectiveRefresh.Partial
         * @since 4.5.0
         */
        self.NavMenuInstancePartial = api.selectiveRefresh.Partial.extend(/** @lends wp.customize.navMenusPreview.NavMenuInstancePartial.prototype */{

            /**
             * Constructor.
             *
             * @since 4.5.0
             * @param {string} id - Partial ID.
             * @param {Object} options
             * @param {Object} options.params
             * @param {Object} options.params.navMenuArgs
             * @param {string} options.params.navMenuArgs.args_hmac
             * @param {string} [options.params.navMenuArgs.theme_location]
             * @param {number} [options.params.navMenuArgs.menu]
             * @param {Object} [options.constructingContainerContext]
             */
            initialize: function( id, options ) {
                var partial = this, matches, argsHmac;
                matches = id.match( /^nav_menu_instance\[([0-9a-f]{32})]$/ );
                if ( ! matches ) {
                    throw new Error( 'Illegal id for nav_menu_instance partial. The key corresponds with the args HMAC.' );
                }
                argsHmac = matches[1];

                options = options || {};
                options.params = _.extend(
                    {
                        selector: '[data-customize-partial-id="' + id + '"]',
                        navMenuArgs: options.constructingContainerContext || {},
                        containerInclusive: true
                    },
                    options.params || {}
                );
                api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );

                if ( ! _.isObject( partial.params.navMenuArgs ) ) {
                    throw new Error( 'Missing navMenuArgs' );
                }
                if ( partial.params.navMenuArgs.args_hmac !== argsHmac ) {
                    throw new Error( 'args_hmac mismatch with id' );
                }
            },

            /**
             * Return whether the setting is related to this partial.
             *
             * @since 4.5.0
             * @param {wp.customize.Value|string} setting  - Object or ID.
             * @param {number|Object|false|null}  newValue - New value, or null if the setting was just removed.
             * @param {number|Object|false|null}  oldValue - Old value, or null if the setting was just added.
             * @return {boolean}
             */
            isRelatedSetting: function( setting, newValue, oldValue ) {
                var partial = this, navMenuLocationSetting, navMenuId, isNavMenuItemSetting, _newValue, _oldValue, urlParser;
                if ( _.isString( setting ) ) {
                    setting = api( setting );
                }

                /*
                 * Prevent nav_menu_item changes only containing type_label differences triggering a refresh.
                 * These settings in the preview do not include type_label property, and so if one of these
                 * nav_menu_item settings is dirty, after a refresh the nav menu instance would do a selective
                 * refresh immediately because the setting from the pane would have the type_label whereas
                 * the setting in the preview would not, thus triggering a change event. The following
                 * condition short-circuits this unnecessary selective refresh and also prevents an infinite
                 * loop in the case where a nav_menu_instance partial had done a fallback refresh.
                 * @todo Nav menu item settings should not include a type_label property to begin with.
                 */
                isNavMenuItemSetting = /^nav_menu_item\[/.test( setting.id );
                if ( isNavMenuItemSetting && _.isObject( newValue ) && _.isObject( oldValue ) ) {
                    _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;
                    }
                }

                if ( partial.params.navMenuArgs.theme_location ) {
                    if ( 'nav_menu_locations[' + partial.params.navMenuArgs.theme_location + ']' === setting.id ) {
                        return true;
                    }
                    navMenuLocationSetting = api( 'nav_menu_locations[' + partial.params.navMenuArgs.theme_location + ']' );
                }

                navMenuId = partial.params.navMenuArgs.menu;
                if ( ! navMenuId && navMenuLocationSetting ) {
                    navMenuId = navMenuLocationSetting();
                }

                if ( ! navMenuId ) {
                    return false;
                }
                return (
                    ( 'nav_menu[' + navMenuId + ']' === setting.id ) ||
                    ( isNavMenuItemSetting && (
                        ( newValue && newValue.nav_menu_term_id === navMenuId ) ||
                        ( oldValue && oldValue.nav_menu_term_id === navMenuId )
                    ) )
                );
            },

            /**
             * Make sure that partial fallback behavior is invoked if there is no associated menu.
             *
             * @since 4.5.0
             *
             * @return {Promise}
             */
            refresh: function() {
                var partial = this, menuId, deferred = $.Deferred();

                // Make sure the fallback behavior is invoked when the partial is no longer associated with a menu.
                if ( _.isNumber( partial.params.navMenuArgs.menu ) ) {
                    menuId = partial.params.navMenuArgs.menu;
                } else if ( partial.params.navMenuArgs.theme_location && api.has( 'nav_menu_locations[' + partial.params.navMenuArgs.theme_location + ']' ) ) {
                    menuId = api( 'nav_menu_locations[' + partial.params.navMenuArgs.theme_location + ']' ).get();
                }
                if ( ! menuId ) {
                    partial.fallback();
                    deferred.reject();
                    return deferred.promise();
                }

                return api.selectiveRefresh.Partial.prototype.refresh.call( partial );
            },

            /**
             * Render content.
             *
             * @inheritdoc
             * @param {wp.customize.selectiveRefresh.Placement} placement
             */
            renderContent: function( placement ) {
                var partial = this, previousContainer = placement.container;

                // Do fallback behavior to refresh preview if menu is now empty.
                if ( '' === placement.addedContent ) {
                    placement.partial.fallback();
                }

                if ( api.selectiveRefresh.Partial.prototype.renderContent.call( partial, placement ) ) {

                    // Trigger deprecated event.
                    $( document ).trigger( 'customize-preview-menu-refreshed', [ {
                        instanceNumber: null, // @deprecated
                        wpNavArgs: placement.context, // @deprecated
                        wpNavMenuArgs: placement.context,
                        oldContainer: previousContainer,
                        newContainer: placement.container
                    } ] );
                }
            }
        });

        api.selectiveRefresh.partialConstructor.nav_menu_instance = self.NavMenuInstancePartial;

        /**
         * Request full refresh if there are nav menu instances that lack partials which also match the supplied args.
         *
         * @param {Object} navMenuInstanceArgs
         */
        self.handleUnplacedNavMenuInstances = function( navMenuInstanceArgs ) {
            var unplacedNavMenuInstances;
            unplacedNavMenuInstances = _.filter( _.values( self.data.navMenuInstanceArgs ), function( args ) {
                return ! api.selectiveRefresh.partial.has( 'nav_menu_instance[' + args.args_hmac + ']' );
            } );
            if ( _.findWhere( unplacedNavMenuInstances, navMenuInstanceArgs ) ) {
                api.selectiveRefresh.requestFullRefresh();
                return true;
            }
            return false;
        };

        /**
         * Add change listener for a nav_menu[], nav_menu_item[], or nav_menu_locations[] setting.
         *
         * @since 4.5.0
         *
         * @param {wp.customize.Value} setting
         * @param {Object}             [options]
         * @param {boolean}            options.fire Whether to invoke the callback after binding.
         *                                          This is used when a dynamic setting is added.
         * @return {boolean} Whether the setting was bound.
         */
        self.bindSettingListener = function( setting, options ) {
            var matches;
            options = options || {};

            matches = setting.id.match( /^nav_menu\[(-?\d+)]$/ );
            if ( matches ) {
                setting._navMenuId = parseInt( matches[1], 10 );
                setting.bind( this.onChangeNavMenuSetting );
                if ( options.fire ) {
                    this.onChangeNavMenuSetting.call( setting, setting(), false );
                }
                return true;
            }

            matches = setting.id.match( /^nav_menu_item\[(-?\d+)]$/ );
            if ( matches ) {
                setting._navMenuItemId = parseInt( matches[1], 10 );
                setting.bind( this.onChangeNavMenuItemSetting );
                if ( options.fire ) {
                    this.onChangeNavMenuItemSetting.call( setting, setting(), false );
                }
                return true;
            }

            matches = setting.id.match( /^nav_menu_locations\[(.+?)]/ );
            if ( matches ) {
                setting._navMenuThemeLocation = matches[1];
                setting.bind( this.onChangeNavMenuLocationsSetting );
                if ( options.fire ) {
                    this.onChangeNavMenuLocationsSetting.call( setting, setting(), false );
                }
                return true;
            }

            return false;
        };

        /**
         * Remove change listeners for nav_menu[], nav_menu_item[], or nav_menu_locations[] setting.
         *
         * @since 4.5.0
         *
         * @param {wp.customize.Value} setting
         */
        self.unbindSettingListener = function( setting ) {
            setting.unbind( this.onChangeNavMenuSetting );
            setting.unbind( this.onChangeNavMenuItemSetting );
            setting.unbind( this.onChangeNavMenuLocationsSetting );
        };

        /**
         * Handle change for nav_menu[] setting for nav menu instances lacking partials.
         *
         * @since 4.5.0
         *
         * @this {wp.customize.Value}
         */
        self.onChangeNavMenuSetting = function() {
            var setting = this;

            self.handleUnplacedNavMenuInstances( {
                menu: setting._navMenuId
            } );

            // Ensure all nav menu instances with a theme_location assigned to this menu are handled.
            api.each( function( otherSetting ) {
                if ( ! otherSetting._navMenuThemeLocation ) {
                    return;
                }
                if ( setting._navMenuId === otherSetting() ) {
                    self.handleUnplacedNavMenuInstances( {
                        theme_location: otherSetting._navMenuThemeLocation
                    } );
                }
            } );
        };

        /**
         * Handle change for nav_menu_item[] setting for nav menu instances lacking partials.
         *
         * @since 4.5.0
         *
         * @param {Object} newItem New value for nav_menu_item[] setting.
         * @param {Object} oldItem Old value for nav_menu_item[] setting.
         * @this {wp.customize.Value}
         */
        self.onChangeNavMenuItemSetting = function( newItem, oldItem ) {
            var item = newItem || oldItem, navMenuSetting;
            navMenuSetting = api( 'nav_menu[' + String( item.nav_menu_term_id ) + ']' );
            if ( navMenuSetting ) {
                self.onChangeNavMenuSetting.call( navMenuSetting );
            }
        };

        /**
         * Handle change for nav_menu_locations[] setting for nav menu instances lacking partials.
         *
         * @since 4.5.0
         *
         * @this {wp.customize.Value}
         */
        self.onChangeNavMenuLocationsSetting = function() {
            var setting = this, hasNavMenuInstance;
            self.handleUnplacedNavMenuInstances( {
                theme_location: setting._navMenuThemeLocation
            } );

            // If there are no wp_nav_menu() instances that refer to the theme location, do full refresh.
            hasNavMenuInstance = !! _.findWhere( _.values( self.data.navMenuInstanceArgs ), {
                theme_location: setting._navMenuThemeLocation
            } );
            if ( ! hasNavMenuInstance ) {
                api.selectiveRefresh.requestFullRefresh();
            }
        };
    }

    /**
     * Connect nav menu items with their corresponding controls in the pane.
     *
     * Setup shift-click on nav menu items which are more granular than the nav menu partial itself.
     * Also this applies even if a nav menu is not partial-refreshable.
     *
     * @since 4.5.0
     */
    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;
            if ( ! e.shiftKey ) {
                return;
            }

            navMenuItemParts = $( this ).attr( 'class' ).match( /(?:^|\s)menu-item-(-?\d+)(?:\s|$)/ );
            if ( navMenuItemParts ) {
                e.preventDefault();
                e.stopPropagation(); // Make sure a sub-nav menu item will get focused instead of parent items.
                api.preview.send( 'focus-nav-menu-item-control', parseInt( navMenuItemParts[1], 10 ) );
            }
        });
    };

    api.bind( 'preview-ready', function() {
        self.init();
    } );

    return self;

}( jQuery, _, wp, wp.customize ) );

All system for education purposes only. For more tools: Telegram @jackleet

Mr.X Private Shell

Logo
-
New File | New Folder
Command
SQL