Reinitializing page scripts after SmoothState.Js p

2019-03-02 04:37发布

I am using SmoothState.js for page transitions and it works fine and loads the new pages with ajax. However, I have JS scripts on each page that need to be reinitialized and I have not been able to get them to always be present on page transitions.

Based on the FAQ:

smoothState.js provides the onAfter callback function that allows you to re-run your plugins. This can be tricky if you're unfamiliar with how AJAX works.

When you run a plugin on $(document).ready(), it's going to register only on elements that are currently on the page. Since we're injecting new elements every load, we need to run the plugins again, scoping it to just the new stuff.

A good way to do this is to wrap your plugin initializations in a function that we call on both $.fn.ready() and onAfter. You'll want to specify the context each time you initialize the plugins so that you don't double-bind them. This is called a "module execution controller".

What my plan has been is to take the functions from my JS files and put them all into an onAfter call inside the SmoothState.js file. That way each time a user changes page, the functions would always be available.

Here the code structure I have now. I've done a lot of digging but I am stuck. Can you help me figure out what I am doing wrong? Thanks for your time!

$(document).ready(function() {
    mail();

});

$('#main').smoothState({
    onAfter: function() {
        mail();
    }
});

function mail() {
    // script from mail.js goes here
}

$(function() {
    $('#main').smoothState();
});

$(function() {
    "use strict";
    var options = {
            prefetch: true,
            pageCacheSize: 3,
            onStart: {
                duration: 250, // Duration of our animation 
                render: function($container) {
                    // Add your CSS animation reversing class 

                    $container.addClass("is-exiting");


                    // Restart your animation 
                    smoothState.restartCSSAnimations();
                }
            },
            onReady: {
                duration: 0,
                render: function($container, $newContent) {
                    // Remove your CSS animation reversing class 
                    $container.removeClass("is-exiting");

                    // Inject the new content 
                    $container.html($newContent);


                }

            },

        },
        smoothState = $("#main").smoothState(options).data("smoothState");
});

2条回答
看我几分像从前
2楼-- · 2019-03-02 05:27

I am working on a website right now which is similar to what you are doing I think.

The way I have done it is, I have two main functions. The first one contains all the functions that need to run only once ever - ie, the stuff to handle Ajax and POPSTATE changes etc. This function runs the 2nd main function at the end. The 2nd main function is a function that contains functions that need to rerun on page changes, it looks for a specific class or ID tag to be in the contents area of the website before running the functions and attaching event listeners to elements on the newly loaded page.

function mainOne() {
    // Set up Ajax, set up any navigation menus that stay constant through pages etc

    // Also runs the 2nd function so that the functions specific to the page
    //   the code loads up on also get run
    mainTwo();
}
function mainTwo() {
    // Contains functions that are specific to pages that can be loaded via AJAX
    /* ie:
    if( $("element-that-only-exists-once-on-one-specific-page").length == 1 ) {
        // Do stuff specific to only this page
    } */
}

In my AJAX function, I call the mainTwo() with every successful page load.

A novel way of making sure that a function runs only once per element, is to add a class to the element you are attaching an event to, for example:

$("div.objects").not(".processed").addClass("processed").click(function(){
    // Stuff to do in the function
});

From what you quoted there, sounds like my mainTwo() function is pretty much what they want you to set up. Basically a main function to hold all your other functions. If you post more code then I can help you sort it out.

查看更多
男人必须洒脱
3楼-- · 2019-03-02 05:29

I managed to get a separate function to run at the end of the code by moving your onAfter script into the main smoothstate function (remove the other smoothstate functions). Run your function on document ready as well in case of browser refresh. If it works the same with your code, it would be as follows:

$(document).ready(function() {
        mail();

    });

    function mail() {
        // script from mail.js goes here
    }

    $(function() {
        "use strict";
        var options = {
                prefetch: true,
                pageCacheSize: 3,
                onStart: {
                    duration: 250, // Duration of our animation 
                    render: function($container) {
                        // Add your CSS animation reversing class 

                        $container.addClass("is-exiting");


                        // Restart your animation 
                        smoothState.restartCSSAnimations();
                    }
                },
                onReady: {
                    duration: 0,
                    render: function($container, $newContent) {
                        // Remove your CSS animation reversing class 
                        $container.removeClass("is-exiting");

                        // Inject the new content 
                        $container.html($newContent);


                    }

                },
                onAfter: function() {
                    mail();
                }
            },
            smoothState = $("#main").smoothState(options).data("smoothState");
    });
查看更多
登录 后发表回答