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.
Related
First of all, sorry for the lame question (probably). I tried to search for an answer but I'm not finding everything I need for my issue.
So... I have a bootstrap website and I am trying to change the page URLS to appear like this :
For example : www.site.com/AboutUs.html - to appear as www.site.com/about-us
I am using the pushState method for this as it follows:
var stateObj = { AboutUs: "about-us" };
history.pushState(stateObj, "About Us", "about-us");
So I get the needed URL address there (www.site.com/about-us).. so far so good. But on page refresh it throws an error stating "The requested URL /about-us was not found on this server."
If I hit the back browser button it goes to www.site.com/AboutUs.html again.(and it is supposed to go on the home page)
My question is :
What am I missing, am I supposed to make a controller and how ?
I am not using C#, I can probably use some help with PHP because I am not good at it. JavaScript / jQuery are welcomed.
Thanks in advance and sorry for the dumb question.
Happy days!
The point of pushState is to be able to say: I have modified the page with JavaScript, the new state is what you would get if you just asked the server for this URL.
You shouldn't use JavaScript for this problem at all. You just want to have a page appear at a particular URL.
You need to configure the server to serve up the content you want on the URL you want.
What am I missing, am I supposed to make a controller and how ?
You need something on the server to handle the URL /about-us.
"A controller" is something you would probably use if you were using the MVC architecture on the server … and it doesn't sound like you are.
More likely you will be wanting to use an Alias, a tool like mod_write, or simply moving the static file to a directory called about-us and renaming it index.html.
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.
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.
Sorry for the badly worded question.
PHP with apache uses index.php/index.html for directory urls like:
localhost = localhost/index.php or localhost/place = localhost/place/index.php
If I start with:
localhost/place
and I use a javascript history.pushstate to update a url with a long adress like:
localhost/place/subplace
then if I enter that url in the browser I'll go to localhost/place/subplace/index.php when I really wanted localhost/place/index.php to allow that url to be the only point of entry.
I'm using simple javascript(window.location.pathname or anchorNode.pathname) to retrieve the url path for use with ajax. This is used by a simple router similar to backbone.js to update the page. The javascript routing works and back/forward in the browser works. If only I could get it to work with the single point of entry for urls entered in the address bar.
To sum up:
I want a single point of entry for my php app to get all subdirectories.
At the single point of entry I want to run the javascript to acquire the path and use it to route the page with ajax.
I'm using history.pushState to update the url, but that messes with the single point of entry for the app when the directories are longer than the main directory. Basically I get a 404 page.
Right now I'm not too concerned with making it backwards compatible with browsers that don't have history.pushState. I just want this one thing to work.
As an addendum I would prefer working with regular paths in javascript and not the query string. Whether the page is loaded with the address bar or the history.pushState is used that's what I would prefer. I don't know if this can be handled with apache rewrite or what.
Similar questions:
How to cope with refreshing page with JS History API pushState
Ok. I'm making things too hard.
To get the routing to work on page load I need to do two things.
In the .htaccess file I can use apache rewrite to make all urls route to index.php?path=first/second/third.
When the page loads just concatenate the the new path in the query string to the javascript string that handles the route.
The javascript is still being used, and there's no duplication of functionality. Everything is good.
This also kind of answers this: How to cope with refreshing page with JS History API pushState
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.