History.js - sharing link of a AJAX loaded page - javascript

I have the following function that activates when I click on some links:
function showPage(page) {
var History = window.History;
History.pushState(null,null,page);
$("#post-content").load(page + ".php");
}
The content of the page updates, the URL changes. However I know I'm surely doing something wrong. For example when I refresh the page, it gives me the Page Not Found error, plus the link of the new page can't be shared, just because of the same reason.
Is there any way to resolve this?

It sounds like you're not routing your dynamic URLs to your main app. Unless page refers to a physical file on your server, you need to be doing some URL rewriting server-side if you want those URLs to work for anything other than simply being placeholders in your browser history. If you don't want to mess with the server side, you'll need to use another strategy, like hacking the URL with hashes. That way the server is still always serving your main app page, and then the app page reads the URL add-on stuff to decide what needs to be rendered dynamically.

You need to stop depending on JavaScript to build the pages.
The server has to be able to construct them itself.
You can then progressively enhance with JavaScript (pushState + Ajax) to transform the previous page into the destination page without reloading all the shared content.
Your problem is that you've done the "enhance" bit before building the foundations.

Related

Force a route cleanly with javascript

I'm working with a legacy app's UI and the path that links to this app is a default:
something/fldr
Whenever that page loads it forces a fldr/landing.asp page. We want to get it to go to other.asp instead of landing.
My approach for this is to use:
if (document.readyState === "interactive") {
if(location.href == 'https://www.something.com/fldr'){
location.href="https://www.something.com/other.asp";
}
}
Doing this causes a page stutter, where the landing.asp loads, shows for like 2 seconds and then refreshes to the correct page.
Is there a standard method for doing something like this in JS or jQuery? I feel like there is a way to make the page hang up until the if statements executes rather than try to load the wrong page. But I can't for the life of me remember what it is. I've handled this on the back end by forcing the correct page to return in the API but I still feel like this is something that can be resolved with only JS.
Note: The route names are made up since this is a stripped down problem of a legacy app.
JavaScript (when running in a browser) is a client-side technology.
That means it cannot run without the page partially loading after the page has been served and sent to the user's browser (client). The browser begins loading resources and parsing scripts and code, and your script will execute in the order it is parsed. This is, in fact, the delay you're experiencing.
While you may possibly tweak this to make the location.href change
execute in some earlier part of this process, there is no way to avoid
a partial page load prior to the client-side redirect you have
implemented.
Essentially, there is a better way to do this, one which will reduce the redirect delay to be imperceptible to a user.
Making this change at the web-server level is the ideal solution; however, first consider, is that even needed?
First, before implementing a redirect, I would suggest to look in the IIS settings and see if there is a default document set to fldr/landing.asp;
You can then just change that setting to make the default document to what you need.
Here's an example for IIS how to do this.
If there is not a default document or if there is some other code or application logic that is forcing landing.asp to load, then you would set up a 301 Permanent Redirect for that URL on the web server.
Here are IIS docs on setting this up.
IF for some reason the above options are unavailable to you (don't have access to web server, etc.), then the best you can do is ensure that script is the first thing in the page before any other scripts, stylesheets, etc., are loaded.
Another hacky thing that might work is just replacing the entire content of landing.asp with other.asp and call it a day :)
That is a last resort of course, and hopefully you can just change the default document and that will handle it.

Pretty URL for static website

I'm creating a "static" website, and I would like to have url like this :
http://www.my-website/my-page-1 or http://www.my-website/my-page-2
I use the jQuery method load() to load the content of my web pages.
Here is my index.html :
<body>
<nav>
<ul >
<li id="my-page-1-menu-item" class="menu-item" onclick="changeState('my-page-1')">
<span><a>Link 1</a></span>
</li>
<li id="my-page-2-menu-item" class="menu-item" onclick="changeState('my-page-2')">
<span><a>Link 2</a></span>
</li>
</ul>
</nav>
<!-- Content, loaded with $.load() -->
<div id="content"></div>
</body>
I know how to change my url without reloading the page, using the history API
Here is my javascript :
function changeState(url) {
window.history.pushState(url, 'Title', url);
loadStateData(url);
}
function loadStateData(state) {
var content = '#content';
$(content).load( 'views/' + state + '.html');
// Manage menu style
$('.menu-item').removeClass('active');
$('#' + state + '-menu-item').addClass('active');
}
With this code I'm able to reach http://www.my-website/my-page-2 by clicking on Link 2, but if I refresh my webpage or if I type http://www.my-website/my-page-2 directly in the browser address bar, I got a 404 error.
I'm not very comfortable with .htaccess URL rewritting but I think it should solve my problem.
And I don't want to use AngularJS, or other framework like that (except if its a really lightweight framework)
You need to ensure that when you use JavaScript to:
Modify the DOM of the current page so it is effectively a different page
Change the URL to identify the different page
…that you also make sure that the server can generate that page itself as well.
That way if the JavaScript fails for any reason then everything will still work. This is a basic principle that best practise is to follow.
This will probably involve duplicating your logic server side, and that will probably be a lot of work. Robustness + client side performance hacks do not work together cheaply. Consider isomorphic JS and taking page snapshots with a headless browser as techniqes to speed this up.
I'm not very comfortable with .htaccess URL rewritting but I think it should solve my problem.
It certainly won't solve it well. You could use it to divert every request back to your homepage (so you have duplicate content on every URL) and then use client side JS to read location and work out what content to load but then you might as well use hashbangs since you'll have thrown out every advantage of using pushState but added duplicate content URLs to your site (and invested a pile of work into creating those duplicate content URLs).
Doing that without any server-side rewrites sounds impossible. When you refresh the page, HTTP server needs to give you contents of proper file, based on URL.
But.. if you really want to make URL rewriting client side you can make one, universal rewrite as it is often done in case of PHP-based websites that do rewriting internally (not by .htaccess or nginx rules, but using PHP script).
When there's no such file like "/my-page-2" on webserver, just redirect client to /index.html?url=/my-page-2 and dispatch to proper subpage using JavaScript.

Handling Dynamic Routes Without a Server

Is it possible to serve a dynamic html page without a backend server or without using a front-end framework like Angular?
Edit
To clarify, the index file is served from a backend. This question is about how to handling routing between the index and dynamic pages.
I have an application that consists of two files - index.html and dynamic.html. When the user clicks an option say "Option A", they are served dynamic.html and the url is updated to /option-a. Now, with a server this is no problem and assuming the user visits the app from the landing page, it isn't a problem either because a cookie can be set. However, suppose a user visits a page at my-domain/option-a. That route doesn't exist and there is no server to redirect so it will 404. They would have to visit dynamic.html.
I think this architecture demands that there's either a server to handle route redirects or a SPA framework.
Is there something I'm missing?
your SPA framework will be active only once your HTML page is loaded and to do that you need to redirect any URL that user tries for your domain to that HTML file. For this you obviously need a server (and since you are talking about my-domain/option-a I assume you have atleast a basic server). You can refer to this link to get an idea on how server can redirect a URL to specific html file: Nodejs - Redirect url.
Once HTML is loaded you can initialize your SPA framework and decide the template to be loaded based on the URL.
Note: without a server you will access URLs using file://somepath/index.html and anything other than this URL will result in 404 and no SPA framework can handle that.
I think the solution is to use a static site generator such as Jekyll or Middleman and allows you to convert information into static pages. That way you functionally are building a bunch of pages but they are all compiled ahead of time. You can add dynamic content that is loaded in from a yaml file and it will compile the content into separate html pages.
It is not possible, but there is a workaround using url parameters like this:
my-folder/index.html
my-folder/index.html?=about
my-folder/index.html?=about/sublevel
my-folder/index.html?=profile
my-folder/index.html?=./games
const urlParams = new URLSearchParams(location.search);
const route = urlParams.get('');
console.log(route);
// Should print "about" "about/sublevel" "profile" "./games"
Of course this approach is not as clean as using a server for routing, but it's the best you can get without a server.
BTW. I tried an alternative solution creating symlinks with all the target routes pointing to the same index.htmlfile. But it did not work because the browser (firefox) redirects by default when it finds a symlink, thus home is shown all the time.

Page-Refresh in a SPA with HTML5 Browser History API?

Instead of using hash URLs for my SinglePageApplication I would like to use the HTML5 Browser History API. This works fine so far (I'm using emberjs).
The pro of the hash URL is, I can refresh the page without worrying about the result. When I try to reload with the browser history API I'll get a 404 (since my server don't have a route for this).
So: Is there a common workaround to avoid this behaviour?
I could tell my server to redirect to the index page but this wouldn't show me the correct content.
Example:
GET host/#images
... shows the "images" page (even when it is the index.html)
GET host/images
... redirect to host/
... shows me the content of the index template
Is https://stackoverflow.com/a/17288940/1423583 an answer to your question? Basically it says that you have to change the server to always serve the index.html page.

replicate google maps URL behaviour with javascript? url+"/#foo"

google map does this thing where if I browse to, say, Australia, the URL changes to
https://www.google.com/maps/#-28.0345854,135.1500838,4z
I'm interested in doing something like this on my web application. So far I have this:
var baseurl = window.location.href.split("/#")[0]
window.history.replaceState( {} , 'foo', baseurl+'/#foo' );
which works just fine for adding "/#foo" to the url
My problem is that, after adding /#foo, the URL doesn't work, it 404es.
I'm not interested in modifying the brower's history, that's why I use replaceState instead of pushState.
anyway, is there a way to do this with js? or do I need server-side code to serve the appropriate page?
thankyou
You "need server-side code to serve the appropriate page". an # character is still part of the URL and therefore needs to be handled by the server. If you want to handle the this kind of situation client side only then what you want is to use # instead. anything after a hash is handle client side and does not trigger a new page to load from the server.
Several libraries use this to replicate routing in a single page HTML only app. For example:
Backbone.js Router
jQuery-Router
jquerymobile-router
Ember.Router
And many more.

Categories

Resources