javascriptphpjqueryajaxwordpress

jQuery AJAX - Redirect to 404 page when load method fails


My website loads all the pages through AJAX, with the jQuery load method. I did my best to adapt this tutorial to Wordpress.

My problem today, is that when the load method returns an error (such as 404 because of a broken link), the AJAX transition doesn't finish, and the page doesn't change at all.

How can I execute something when the load method fails?

EDIT: I found a solution for that in the docs.

section.load(url + ' .cd-main-content > *', function (response, status, xhr) {
    //the code
}

Now it doesn't help me as I thought it would. Because, response returns the 404 page content as expected, status returns error and xhr [object OBJECT]. What I don't get is why the response html isn't being loaded in the div...

How can I know this is a 404 error?

Successfully checked for a 404 error using :

if (status == "error" && xhr.status == "404") {
    console.log('this is a 404 error');
}

I tried executing my code in the load function conditionally if the xhr.status is 404 or if the status is success, with no luck. Still not working. Can anybody help?

How can I redirect to wordpress's 404.php page with jQuery?

How should I treat other error codes?

Lots of questions sorry... I don't know where to start

Here's the Javascript:

jQuery(document).ready(function (event) {
    
    // select website's root url
    var rootUrl = aws_data.rootUrl; 
    var isAnimating = false, 
        newLocation = '', 
        firstLoad = false;
    
    // Internal Helper
    $.expr[':'].internal = function(obj, index, meta, stack){
        // Prepare
        var
            $this = $(obj),
            urlinternal = $this.attr('href')||'',
            isInternalLink;

        // Check link
        isInternalLink = urlinternal.substring(0,rootUrl.length) === rootUrl || urlinternal.indexOf(':') === -1;

        // Ignore or Keep
        return isInternalLink;
    };
     
    //trigger smooth transition from the actual page to the new one, excluding event on non relevant links  
    $('main').on('click', 'a[href]:internal:not(.no-ajaxy,.love-button,[href^="#"],[href*="#respond"],[href*="wp-login"],[href*="wp-admin"])', function (event) { 
        event.preventDefault();
        //detect which page has been selected
        var newPage = $(this).attr('href');
        //if the page is not already being animated - trigger animation
        if (!isAnimating) changePage(newPage, true);
        firstLoad = true;
    });
    //detect the 'popstate' event - e.g. user clicking the back button
    $(window).on('popstate', function (e) {
        if (firstLoad) {
            /*
            Safari emits a popstate event on page load - check if firstLoad is true before animating
            if it's false - the page has just been loaded 
            */
            var newPageArray = location.pathname.split('/'), //this is the url of the page to be loaded 
                //newPage = newPageArray[newPageArray.length - 1];
                newPage = window.location.href;
            if (!isAnimating && newLocation != newPage) changePage(newPage, false);
        }
        firstLoad = true;
    });

    function changePage(url, bool) {
        isAnimating = true;
        // trigger page animation
        $('body').addClass('page-is-changing');
        $('.cd-loading-bar').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function () {
            loadNewContent(url, bool);
            newLocation = url;
            $('.cd-loading-bar').off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
        });
        //if browser doesn't support CSS transitions
        if (!transitionsSupported()) {
            loadNewContent(url, bool);
            newLocation = url;
        }
    }

    function loadNewContent(url, bool) {
        // I don't understand the line below
        url = ('' === url) ? rootUrl : url; 
        var newSection = 'cd-' + url.replace(rootUrl, ""); 
        var section = $('<div class="cd-main-content ' + newSection + '"></div>');
        // this ajax request helps me applied Wordpress classes on the body element, which is not being reloaded below
        $.ajax({url: url, 
            success: function(data){
                data = data.replace("<body", "<container").replace("body>", "container>");
                var classes = $(data).filter("container").attr("class"); 
                $("body").attr("class", classes + " page-is-changing"); 
            } 
        });
        
        section.load(url + ' .cd-main-content > *', function (event) {
            // load new content and replace <main> content with the new one
            $('main').html(section);
            var delay = 1200; 
            
            //functions to execute after DOM is loaded
            $(document).foundation();
            makeFooterSticky();
            window.scrollTo(0, 0);
            $(".ajax-load-more-wrap").ajaxloadmore();
            //ga('send', 'pageview', window.location.pathname);
            
            setTimeout(function () {
                //wait for the end of the transition on the loading bar before revealing the new content
                $('body').removeClass('page-is-changing');
                $('.cd-loading-bar').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function () {
                    isAnimating = false;
                    $('.cd-loading-bar').off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
                });
                if (!transitionsSupported()) isAnimating = false;
            }, delay);
            if (url != window.location && bool) {
                //add the new page to the window.history
                //if the new page was triggered by a 'popstate' event, don't add it
                window.history.pushState({
                    path: url
                }, '', url);
            }
        });
        
    }

    function transitionsSupported() {
        return $('html').hasClass('csstransitions');
    }
});

Solution

  • I finally solved my problem.

    After realizing that the response returned what I wanted, I took a guess and assumed that the problem was that the status returned was 404 when in fact, 200 was what I wanted.

    So I added status_header(200); at the beginning of my 404.php file and now it works perfectly.

    I hope it's not problematic to ditch the 404 status code but that's my only solution for now.