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();
})