How to handle URL with parameters in a SAP AJAX Webapp? - javascript

I'm writing a Wordpress/AJAX based SAP web application, and I have a question about URL handling.
My application (roughly) looks like this:
There is an index.php file which basically contains a page container and the client-side code to handle ajax calls.
The client-side code is responsible for switching the pages according to user clicks. It does that by calling the registered action, which is mapped to a server-side function that returns the html for that page. (So there is a function named get_about_page() that prints/returns the HTML of the requested page)
The problem with this setup is handling URLs.
The question at hand is how do I handle requests to URLs like http://domain.com/about, for example?
Had I had an about.php page, I could add a rewrite rule to direct all requests there.
I could also, theoretically, parse the URL on the client-side, and decide which ajax call to fire, but that seems like a bad idea.

Use pre define wordpress api, it may help you

Related

Dynamically returning a sitemap with Vue.js

I am working on a vue js project which has multiple tenants. I am trying to find a solution where I can dynamically generate an xml file for each tenant. Tenants are identified by the url, so example.com/sitemap.xml would be one sitemap, tenant 2 would be example1.com/sitemap.xml and a different sitemap. Both of the urls hit the same server but load different data because of their domain. In turn I need to make the sitemap.xml dynamically generated as well.
I have been doing some research and I have used routes in my project but I'm not sure if I can set a route for an actual filename, and if so is it possible to return an xml response straight from vue through javascript. I previously tried something similar for generating html outside of my application. So I had a route call it /test, which would load a component called test, the component would then have javscript code that replaces the html document with some other html. Would this possibly be an approach to use?
https://www.npmjs.com/package/vue-router-middleware
I also found the package above and another similar one, that looks to do what I need by allowing me to intervene between route changes. However, I am not sure if this will allow me to return xml, the example seems to have logic and then end with next(), wondering if instead of calling next I can actually just return the xml document at that point.
Any help would be much appreciated.
Thank you.
If you have a regular Vue app, it is running on the client side not the server side. So for all routes, your webserver returns index.html. Once loaded, vue router initialises on the client and detects the route to show the appropriate view/components.
So a request to example.com/sitemap.xml returns index.html
I would guess that web crawlers are expecting the following header in the response, and the response body of an XML document for sitemaps.
content-type: text/xml;
You may be able to generate on the client side if crawlers run the javascript but I would suggest it is better to generate server side and return plain old XML. Your server side code should be able to generate this and switch based on the tenant.
Then in the server put a special route for /sitemap.xml to not return the vue app

How to map a custom URL to a REST resource in an SPA?

I have a design issue with my SPA, and hope someone can give me some direction. A user profile page is rendered like this:
The browser fetches /some-username.
The server checks to see if the request was a XMLHTTPRequest or not. It is not, and so it simply returns the bundled javascript app to the browser to execute.
The javascript bundle is executed in the browser, it sees the current URL and makes an AJAX request, again to /some-username.
The server sees the XMLHTTPRequest header, looks up the user who has the custom URL "/some-username" and returns the JSON data about the user back to the javascript to render.
This feels wrong. The app should be making RESTful requests to /users/:id to fetch the user data. But how can it know the id that corresponds to the user with the URL /some-username?
It is worth adding an extra HTTP request just to look up the resource identifier? Something like /get_user_id?url=/some-username.
Are you flexible about your API? If so you may change /some-username to /user-id or if you want to include username /user-id/username but ignore username.
As alternative it is also common to make requests in a filter form. Like /users?username=peter
And feel free to use /users/peter if your username identifies the user. Becuase it's actualy the id (that doesn't have to be integer) and then your url is exactly /users/:id
There is nothing "unRESTful" about /some-username. It's just another resource. The response - I hope - contains the canonical URL /user/id anyway, either as a header or as some kind of "self" link.
That's also how you could achieve your goal. Embed the URL in the page either as JavaScript or as a header equivalent (unfortunately you cannot read the headers of the page request with JavaScript):
//header. Can also use a custom header like X-User-Location
<meta http-eqiv="Location" content="/user/id">
//JavaScript
<script>
var userURL = '/user/id
</script>
I recommend keeping your current approach.

Page Load alternative in a Pure HTML AJAX Website

I am working on a pure HTML website, all pages are HTML with no relation to any server side code.
Basically every request to the server is made using AJAX, I send data from forms, I process this data in Handlers, then I return a JSON string that will be processed back on the client side.
Let's say the page is loaded with parameters in the URL, something like question.html?id=1. Earlier, I used to read this query string on Page Load method, then read data from the database and so on...
Now, since its pure HTML pages, I'm trying to think of an approach that will allow me to do the same, I have an idea but its 99% a bad idea.
The idea is to read URL parameters using JS (after the page has loaded), and then make an AJAX request, and then fetch the data and show them on the page. I know that instead of having 1 request to the server (Web Forms), we are now having 2 Requests, the first request to get the page, and the second request is the AJAX request. And of course this has lots of delays, since the page will be loaded at the beginning without the actual data that I need inside it.
Is my goal impossible or there's a mature approach out there?
Is my goal impossible or there's a mature approach out there?
Lately there are a good handful of JavaScript frameworks designed around this very concept ("single page app") of having a page load up without any data pre-loaded in it, and accessing all of the data over AJAX. Some examples of such frameworks are AngularJS, Backbone.js, Ember.js, and Knockout. So no, this is not at all impossible. I recommend learning about these frameworks and others to find one that seems right for the site you are making.
The idea is to read URL parameters using JS (after the page has loaded), and then make an AJAX request, and then fetch the data and show them on the page.
This sounds like a fine idea.
Here is an example of how you can use JavaScript to extract the query parameters from the current page's URL.
I know that instead of having 1 request to the server (Web Forms), we are now having 2 Requests, the first request to get the page, and the second request is the AJAX request. And of course this has lots of delays, since the page will be loaded at the beginning without the actual data that I need inside it.
Here is why you should not worry about this:
A user's browser will generally cache the HTML file and associated JavaScript files, so the second time they visit your site, the browser will send requests to check whether the files have been modified. If not, the server will send back a short message simply saying that they have not been modified and the files will not need to be transmitted again.
The AJAX response will only contain the data that the page needs and none of the markup. So retrieving a page generated on the server would involve more data transfer than an approach that combines a cacheable .html file and an AJAX request.
So the total load time should be less even if you make two requests instead of one. If you are concerned that the user will see a page with no content while the AJAX data is loading, you can (a) have the page be completely blank while the data is loading (as long as it's not too slow, this should not be a problem), or (b) Throw up a splash screen to tell the user that the page is loading. Again, users should generally not have a problem with a small amount of load time at the beginning if the page is speedy after that.
I think you are overthinking it. I'd bet that the combined two calls that you are worried about are going to run in roughly the same amount of time as the single webforms page_load would if you coded otherwise - only difference now being that the initial page load is going to be really fast (because you are only loading a lightweight, html/css/images page with no slowdown for running any server code.
Common solution would be to then have a 'spinner' or some sort (an animated GIF) that gives the user an visual indication that the page isn't done loading while your ajax calls wait to complete.
Watch a typical page load done from almost any major website in any language, you are going to see many, many requests that make up a single page being loaded, wether it be pulling css/images from a CDN, js from a CDN, loading google analytics, advertisements from ad networks etc. Trying to get 100% of your page to load in a single call is not really a goal you should be worried about.
I don't think the 2-requests is a "bad idea" at all. In fact there is no other solution if you want to use only static HTML + AJAX (that is the moderm approach to web development since this allow to reuse AJAX request for other non-HTML clients like Android or iOS native apps). Also performance is very relative. If your client can cache the first static HTML it will be much faster compared to server-generated approach even if two requests are needed. Just use a network profiler to convince yourself.
What you can do if you don't want the user to notice any lag in the GUI is to use a generic script that shows a popup hiding/blocking all the full window (maybe with a "please wait") until the second request with the AJAX is received and a "data-received" (or similar) event is triggered in the AJAX callback.
EDIT:
I think that probably what you need is to convert your website into a webapp using a manifest to list "cacheable" static content. Then query your server only for dynamic (AJAX) data:
http://diveintohtml5.info/offline.html
(IE 10+ also support Webapp manifests)
Moderm browsers will read the manifest to know whether they need to reload static content or not. Using a webapp manifest will also allow to integrate your web site within the OS. For example, on Android it will be listed in the recent-task list (otherwise only your browser, not your app is shown) and the user can add a shorcut to the desktop.
So, you have static HTMLs and user server side code only in handlers? Why you can't have one ASP .Net page (generated on server side) to load initial data and all other data will be processed using AJAX requests?
if its possible to use any backed logic to determine what to load on server side, that will be easy to get the data.
say for example if you to load json a int he page cc.php by calling the page cc.php?json=a, you can determine from the PHP code to put a json into the page it self and use as object in your HTML page
if you are using query string to read and determine, what to load you have to make two calls.
The primary thing you appear to want is what is known as a router.
Since you seem to want to keep things fairly bare metal, the traditional answer would be Backbone.js. If you want even faster and leaner then the optimised Backbone fork ExoSkeleton might be just the ticket but it doesn't have the following that Backbone proper has. Certainly better than cooking your own thing.
There are some fine frameworks around, like Ember and Angular which have large user bases. I've been using Ember recently for a fairly complex application as it has a very sophisticated router, but based on my experiences I'm more aligned with the architecture available today in React/Flux (not just React but the architectural pattern of Flux).
React/Flux with one of the add-on router components will take you very far (Facebook/Instrgram) and in my view offers a superior architecture for web applications than traditional MVC; it is currently the fastest framework for updating the DOM and also allows isomorphic applications (run on both client and server). This represents the so called "holy grail" of web apps as it sends the initial rendered page from the server and avoids any delays due to framework loading, subsequent interactions then use ajax.
Above all, checkout some of the frameworks and find what works best for you. You may find some value comparing framework implementations over at TodoMVC but in my view the Todo app is far too simple and contrived to really show how the different frameworks shine.
My own evolution has been jQuery -> Backbone -> Backbone + Marionette -> Ember -> React/Flux so don't expect to get a good handle on what matters most to you until you have used a few frameworks in anger.
The main issue is from a UX / UI point of view.
Once you get your data from the server (in Ajax) after the page has been loaded - you'll get a "flickering" behavior, once the data is injected into the page.
You can solve this by presenting the page only after the data has arrived, OR use a pre-loader of some kind - to let the user know that the page is still getting its data, but then you'll have a performance issue as you already mentioned.
The ideal solution in this case is to get the "basic" data that the page needs (on the first request to the server), and manipulate it via the client - thus ease-in the "flickering" behavior.
It's the consideration between performance and "flickering" / pre-loading indication.
The most popular library for this SPA (Single Page Application) page - is angularJS
If I understand your inquiry correctly. You might want to look more about:
1) window.location.hash
Instead of using the "?", you can make use of the "#" to manipulate your page based on query string.
Reference: How to change the querystring on the same page without postback
2) hashchange event
This event fires whenever there's a changed in the fragment/hash("#") of the url. Also, you might want to track the hash to compare between the previous hash value and the current hash value.
e.g.
$(window).on('hashchange', function () {
//your manipulation for query string goes here...
prevHash = location.hash;
});
var prevHash = location.hash; //For tracking the previous hash.
Reference: On - window.location.hash - Change?
3) For client-side entry-point or similar to server-side PageLoad, you may make use of this,
e.g.
/* Appends a method - to be called after the page(from server) has been loaded. */
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function () {
if (oldonload) {
oldonload();
}
func();
}
}
}
function YourPage_PageLoad()
{
//your code goes here...
}
//Client entry-point
addLoadEvent(YourPage_PageLoad);
Since you're doing pure ajax, the benefit of this technique is you would be able to easily handle the previous/next button click events from the browser and present the proper data/page to the user.
I would prefer AngularJS. This will be a good technology and you can do pagination with one HTML. So i think this will be good framework for you as your using static content.
In AngularJS MVC concept is there please read the AngularJS Tutorial. So this framework will be worth for your new project. Happy coding

Getting backbone routing to work with pushstate and node.js/express as server

I'm trying to build a single page app with backbone.js on front end and node.js/express as server, I want to have a base HTML file for the root, and then when user navigates to any path such as
mydomain.com/foo/bar
I want to be able to handle that path on the client side by javascript instead of making a round trip to server. I am reading about backbone routing and HTML5 push state. In this article he describes push state like this,
In fact, PushState is really nothing more than a standard API for JavaScript, that allows us to manipulate the browser history by “push”ing full URLs into the browser’s URL without making a round trip to the server, and respond to changes in the URL with Javascript – all without the use of URL hash fragments.
but when I use push state it does actually makes a server request and expects server to deliver contents under /foo/bar . I don't understand how I can avoid that.
Now let's assume that even with push state, your client is going to make a server request under mydomain.com/foo/bar when you visit this URL directly. In that case, since I'm serving the default HTML file, and this default HTML file has links to scripts in it:
<script type="text/javascript" src="/scripts/myscript.js" ></script>
When this HTML loads, it starts looking for scripts under /foo directory instead of root since the server was requested under /foo which obviously does not exist. How do I fix this?
I'm really confused at this point. I'd like to know how URL routing is usually done in a single page application. Any help will be greatly appreciated. You can also refer to this other question I have posted about the same issue: Backbone Router : Get rid of # in the URL
The solution you're trying to implement is very interesting but not that simple. When your server gets a request to mydomain.com/foo/bar, you should redirect to your root with some parameter that the frontend (JavaScript) app can pick-up to know what the original request was for. For example:
Client sends GET http://mydomain.com/foo/bar
Server redirects (responds 302 with Location header set) to http://mydomain.com/#!/foo/bar
Your SPA is loaded in the browser, and on startup you check for the hash and find #!/foo/bar, so you remove the hash and trigger the /foo/bar route (that's a push-state). Your resulting URL is again http://mydomain.com/foo/bar: the original URL the user browsed to.
Grooveshark does something similar to this, though it actually responds with a page to the request sent in 1., which does the hash replacement in the client and then sends another request to the server. It looks unnecessary to me, maybe I'm overlooking something.

History.pushState and page refresh

I started looking at HTML5 new history API
However, I have one question. How can one handles the page refresh?
For example a user clicks a link, which is handled by a js function, which
asynchronously loads the content of the page
changes the URL with history.pushState()
The the user refreshes the page, but the URL of course does not exist on the server
How do you handle situations like this? With the hash solution there was no issue there
Thanks
This does require the server-side support. The ideal use of .pushState is to allow URLs from JavaScript applications to be handled intelligently by the server.
This could be either by re-serving the same JavaScript application, and letting it inspect window.location, or by rendering the content at that URL on the server as you would for a normal web application. The specifics obviously vary depending on what you're doing.
You need to perform server side redirection for copy and pasted fake URLs
It all depends on what server side technology you're using. There is no JavaScript way but writing a crazy function in your 404 page that redirect user based on incoming URL that is not a good solution.
The the user refreshes the page, but the URL of course does not exist
on the server
What do you mean by this? I have a feeling your assumption is wrong.
Actually yes, the point is it is the developer who should provide (serverside or clientside) implementation of url-to-pagestate correspondence.
If, once again, I've get the question right.
If you are using ASP.NET MVC on your server, you can add the following to your RegisterRoutes function:
routes.MapRoute(
name: "Default",
url: "{*url}",
defaults: new { controller = "Home", action = "Index" }
);
This will send all requests to Index action of your HomeController and your UI will handle the actual route.
For people looking for a JS-only solution, use the popstate event on window. Please see MDN - popstate for full details, but essentially this event is passed the state object you gave to pushState or replaceState. You can access this object like event.state and use it's data to determine what to do, ie show an AJAX portion of a page.
I'm not sure if this was unavailable in 2011 but this is available in all modern browsers (IE10+), now.

Categories

Resources