Implementing Dynamic Loading with jQuery Load and Browser Navigation Handling

This follows up on the previous article about using jQuery's load method for dynamic content loading and resolving JavaScript execution issues in loaded pages. However, the current implementation still has usability problems related to browser navigation behaviors such as forward/backward buttons and page refreshes. Several developer have encountered similar challenges, so this article focuses on enhancing user experience by properly handling these navigation scenarios.

While researching solutions, most results pointed to custom plugins that are outdated and lack proper support for newer jQuery versions. Some approaches used HTML5's history API, which is now widely supported across modern browsers. For users still supporting legacy IE versions, this approach may not be suitable.

Building upon the earlier work, I've wrapped the jQuery plugin functionality with enhanced structure. The core load mechanism was already explained in the previous article, so we'll focus on the history API integration:

history.pushState(data, title [, url]): Adds a new entry to the browser's history stack. The data parameter is passed to the onpopstate event handler; title is currently ignored by all browsers; url is optional and defaults to the current page URL.

Custom plugin implementation:

 1 $.extend({
 2     /**
 3      * Loads content via jQuery's load method,
 4      * fetching content within the specified URL that matches ID 'content'
 5      * into the current page's element with ID 'content'
 6      * url        target URL
 7      * data       request parameters
 8      */
 9     loadPage: function(url, data) {
10         $.ajaxSetup({cache: false });
11         $("#content").load(url+ " #content ", data, function(result){
12             // Execute JavaScript from loaded page in current context
13             $result = $(result); 
14             // Pass parameters to loaded page through param variable
15             $result.find("script").prepend("var param = "+JSON.stringify(data)).appendTo('#content');
16         });
17     },
18     /**
 9      * Stores navigation state including URL, menu identifier, and parameters
10      * url        target URL
11      * menuId     menu identifier
12      * data       request parameters
13      */
14     pushState : function(url, menuId, data) {
15         console.log("pushState:"+url+":::"+ menuId+":::"+ data)
16         
17         // Use parent menu ID if current menu ID is missing
18         if(menuId == null || menuId == ''){
19             menuId = history.state.menuId;
20         }
21         // Store navigation metadata in browser history
22         history.pushState({urlStr : url, menuId : menuId, data : data}, "Page Title", "?_url="+url);
23     },
24     /**
 5      * Handles browser back/forward navigation events
 6      */
25     popState : function(){
26         window.addEventListener("popstate", function() {
27             var currentState = history.state;
28             if(currentState!=null){
29                 url = ".."+currentState.urlStr;
30                 this.menuOpen(currentState.menuId);
31                 var primitiveUrl = currentState.urlStr.split("#")[0];
32                 $.loadPage(url, currentState.data);
33             }
34         });
35     },
36     /**
 7      * Handles page refresh events
 8      */ 
39     refresh : function(){
40         var currentState = history.state;
41         if(currentState!=null){
42             loadUrl = ".."+currentState.urlStr;
43             var primitiveUrl = currentState.urlStr.split("#")[0];
44             var page = loadUrl.split("#")[1];
45             pageScript = "";
46             if(page !=null){
47                 pageScript = " $table.page("+page+").draw(false);";
48             }
49             $.loadPage(loadUrl, currentState.data);
50         }
51     },
52     /**
 53      * Menu tree expansion functionality
 64      * menuId     identifier of target menu item
 75      */
76     menuOpen : function(menuId){
77         $("#leftMenu").find(".active").removeClass("active");
78         $("#leftMenu").find("ul").css({"display":"none"});
79         
80         $("#"+menuId).addClass("active");
81         $("#"+menuId).parents("li").addClass("active");
82         $("#"+menuId).parents("ul").addClass("menu-open").css({"display":"block"});
83     }
84 });

Usage example:

/*
    * Content loading function, where url parameter refers to DOM elements containing href attributes,
    * Usage example: <span onclick="javascript:load(this);" href="/backstage/website/test.html">Test</span>
    * Note: 1. Avoid using anchor tags as they navigate away from current page
    *       2. Target content must be marked with id="content" 
    *       3. Page-specific JavaScript should be placed within content area
    */
    function load(url, data){
        // Extract URL
        var urlStr =  $(url).attr("href");
        var urlStr = urlStr.split("..")[1]; // Get menu ID
        var menuId = $(url).attr("id");
        $.pushState(urlStr, menuId, data);
        // Load target page content
        $.loadPage($(url).attr("href"), data);
    }
 
    /*
        Browser navigation event handlers
    */
    $.popState();
     
    /*
    * Refresh event handler
    */
    $(function(){
        $.refresh();
    })

Tags: jquery Ajax HTML5 history-api Navigation

Posted on Mon, 02 Nov 2026 16:12:04 +0000 by eyalrosen