admin管理员组

文章数量:1122826

I have this script that cuts down my menu and adds a "+" dropdown if there are too many menu items in an attempt to prettify long menus, as such:

Without the script running:

Which I call in functions.php with:

function _s_scripts() {
    wp_enqueue_script( 'main', get_template_directory_uri() . '/js/main_res.js', array( 'jquery' ), '', false );
}
add_action( 'wp_enqueue_scripts', '_s_scripts' );

Unfortunately, this results in late-execution and jagginess. Is there any way I can hook this script into "as soon as you're done generating X part (menu)" do this?

The effect is very noticeable for the user:

.jpg

and here's the script, just for testing purposes, main_res.js:

function sliceMenu(desired_len) {
    var menu_len = document.querySelectorAll('#primary-menu > li').length;

    if (menu_len > desired_len) {

        var append_menu_el = document.createElement('div');
        append_menu_el.innerHTML = ('<div id="js-cover-menu"><img class="plus" src="$PATH/svg/plus_menu.svg" alt="more-menu"></div>').replace('$PATH', ABSPATH);
        document.getElementById('primary-menu').parentNode.appendChild(append_menu_el);

        let diff = menu_len - desired_len;
        let sliced_lis = [...(document.querySelectorAll('#primary-menu > li'))].slice(-diff);


        var js_menu_el = document.createElement('ul');
        js_menu_el.setAttribute('id', 'js-cover-menu-dropdown');
        document.getElementById('js-cover-menu').appendChild(js_menu_el);

        js_cover_menu_el = document.getElementById('js-cover-menu-dropdown');

        for(var i = 0, length = sliced_lis.length; i < length; i++) {
            js_cover_menu_el.appendChild(sliced_lis[i]);
        }
        document.querySelectorAll('#js-cover-menu-dropdown > li > ul').forEach(node => node.remove());
    } else {
        return;
    }
}

I have this script that cuts down my menu and adds a "+" dropdown if there are too many menu items in an attempt to prettify long menus, as such:

Without the script running:

Which I call in functions.php with:

function _s_scripts() {
    wp_enqueue_script( 'main', get_template_directory_uri() . '/js/main_res.js', array( 'jquery' ), '', false );
}
add_action( 'wp_enqueue_scripts', '_s_scripts' );

Unfortunately, this results in late-execution and jagginess. Is there any way I can hook this script into "as soon as you're done generating X part (menu)" do this?

The effect is very noticeable for the user:

https://i.sstatic.net/9270D.jpg

and here's the script, just for testing purposes, main_res.js:

function sliceMenu(desired_len) {
    var menu_len = document.querySelectorAll('#primary-menu > li').length;

    if (menu_len > desired_len) {

        var append_menu_el = document.createElement('div');
        append_menu_el.innerHTML = ('<div id="js-cover-menu"><img class="plus" src="$PATH/svg/plus_menu.svg" alt="more-menu"></div>').replace('$PATH', ABSPATH);
        document.getElementById('primary-menu').parentNode.appendChild(append_menu_el);

        let diff = menu_len - desired_len;
        let sliced_lis = [...(document.querySelectorAll('#primary-menu > li'))].slice(-diff);


        var js_menu_el = document.createElement('ul');
        js_menu_el.setAttribute('id', 'js-cover-menu-dropdown');
        document.getElementById('js-cover-menu').appendChild(js_menu_el);

        js_cover_menu_el = document.getElementById('js-cover-menu-dropdown');

        for(var i = 0, length = sliced_lis.length; i < length; i++) {
            js_cover_menu_el.appendChild(sliced_lis[i]);
        }
        document.querySelectorAll('#js-cover-menu-dropdown > li > ul').forEach(node => node.remove());
    } else {
        return;
    }
}
Share Improve this question edited Feb 11, 2018 at 12:15 Jonathan Guerin asked Feb 10, 2018 at 23:04 Jonathan GuerinJonathan Guerin 3551 silver badge14 bronze badges 4
  • "Late execution" is what I read. Imagine it's true. And there is no reason to paste JavaScript here when it's not a part of WordPress. – Max Yudin Commented Feb 10, 2018 at 23:19
  • @MaxYudin I understand, but the question is not about the JS code at all, it's about how WordPress handles that code. – Jonathan Guerin Commented Feb 11, 2018 at 1:31
  • If so, remove JavaScript from the question to make it clean, simple and free of clutter. You'll get more chances to be read and answered. – Max Yudin Commented Feb 11, 2018 at 6:14
  • @MaxYudin Great feedback, analyzed and implemented. – Jonathan Guerin Commented Feb 11, 2018 at 12:16
Add a comment  | 

2 Answers 2

Reset to default 0

First of all, if you are not using jQuery, then do not pass the jQuery as a dependency to the wp_enqueue_script() function.

Now, about your question. It's not really WordPress related, but anyway. You didn't mention how you call this function, since that's all that matters here. If you output your code lately, such as in the footer, it won't run until everything before that part is loaded. My suggestion is, to use a child them and add the code directly after your menu is output, and call the function. This way, the script will run immediately after the menu is created, and since no jQuery is required, you won't have a problem using it.

It looks like your script is partially using vanilla javascript. If you can get rid of its dependence on jQuery then you can just stick it right into a script tag in your footer.

However, scripts that are run on $( document ).ready() will always have this effect if you are changing the html of the page.

Your 2 solutions are: write the script properly in php, by setting up the hidden items with CSS classes so they don't show on page load, and use javascript logic to add click handlers to the "+".

Another slightly more hacky option, is to hide the div with CSS, and at the end of your javascript, apply a CSS class that shows it. Now the page will load with nothing, and a split second later, the menu will become visible. This is a bit better than the menu loading looking one way, and then changing completely after the page loads.

本文标签: How can I make sure my JS script gets executed firstamong other scripts