well, with my specific situation I had thousands of products organized in categories and sub categories. Well..thats a ton of urls and controllers to write. so what i did was make a category template, a sub category template and a product page template. then made routes like below in my application/config/routes.php file:
$route['products'] = 'products/index';
//so i know now they are on a category page and $1 is the name of the category.
//i can go query my db and get all subcategorys and the products under each now.
$route['products/(:any)'] = 'products/category/$1';
//the 1 and 2 here are category and subcategory from the url. so i know from this to
//use these in my query to grab all products in this category and subcategory.
$route['products/(:any)/(:any)'] = 'products/subcategory/$1/$2';
//i know this is gonna be a product page. and i know the category, the sub category and the product name. in this case all i really need is the product name since there is only one product with that name.
$route['products/(:any)/(:any)/(:any)'] = 'products/details/$1/$2/$3';
in your situation you can do the same. use your urls, your taking the time to build them so use them. in javascript you can send them back to your controllers via 'window.location.pathname'; all you have to do is split it up and you can use the same mentality to load a page and know exactly where you are at.
Also, in your ajax url property make sure your url is either an absolute url, or it references the root first. I think i know what your issue is. you are using a url like "users/dashboard" in your url property when it should be "/users/dashboard" you need to always go to the root and get the controller, otherwise it uses the url and will always take on the "users/dashboard" to the current url you are on. So if you are on "users/dashboard" and go load it again, your actually telling it to load "/users/dashboard/users/dashboard" and this becomes an infinite loop. Just put a backslash in front of your url and it will always reference the root.