Force a route cleanly with javascript - 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.

Related

Control execution of JavaScript function only once

I have 5 html pages and a JavaScript function DoInitialConfiguration() in a JavaScript File. User can open any of the five html pages and I want that irrespective of which page is opened, I call this function on the first page access. But also want to remember that the function has been called once and not call it in other page load. I only have these 5 html pages and the JavaScript file which has the function. I am owner of the JavaScript file but can do limited change in the html pages (which I don't own) like load the JavaScipt file and call the function DoInitialConfiguration().
Since the JavaScript file will remain in browser cache, is there a way to remember the function has been called once by using any variable in the JS file. It is OK to call DoInitialConfiguration() again if the page is reloaded after clearing browser cache.
how can this functionality be achieved
If your 5 pages are hosted under same site (which probably would be the case), you can use localStorage to add a key to check if your script was called first time or not.
if (localStorage.getItem("firstRun") != null) {
// second run+ code goes here
} else {
localStorage.setItem("firstRun", "ohyes");
// first run code goes here
}
You can possibly use localStorage for this. Once your code executes set a localStorage variable i.e. localStorage.setItem(<key>, <value>) and in the function check if the localStorage has been set i.e. localStorage.getItem("lastname"). If its set do not execute the code.
It would be good to understand you setup and case study better.
If I understand you correctly, you have 5 separate HTML pages (and you are not running a Single Page Application [SPA]) then what you want to do is impossible through browser and cache memory alone. If you want to remember settings you need to save these using localStorage or cookies (as some of the answers popped up have suggested) but as they are 5 different html pages what does the Js do to make you not want to re-run it on a second page load?

Insert JavaScript into WebView before pageload

I have a little problem while inserting JavaScript into my WebView before the page is loaded.
The reason why I want to insert JavaScript ist because I can't pass JSON to Java via a JavascriptInterface. I don't want to use strings or JSON.stringify while developing the WebApps so my approach was to add some JavaScript inside the WebViewClient.onPageStarted() method.
simplified example:
var JSWrapper = {
callJavascriptInterface: function (str, obj) {
if (typeof obj === 'object') {
JavascriptInterface.function(str, JSON.stringify(obj));
} else {
JavascriptInterface.function(str);
}
}
}
inside onPageStarted I also unregister sensors and remove old callbacks I registered via JavascriptInterfaces, cause they should be enabled anymore when the site has changed.
That works when I change the site via a link or something but if I use window.location.reload() I end up with errors (JSWrapper not defined).
Does someone have an idea how to solve this problem or maybe even a better approach for turning off the sensors, removing callbacks and the JSON.stringify?
onPageStarted is not a good place for doing anything with the page. It is called right after the moment when the first reply has been obtained from the server, and may happen before the page has been actually processed by the rendering engine. Thus, depending on the speed of page loading, you might end up interacting with the previously loaded page, which will be discarded (together with your changes) soon.
Another point to keep in mind is that changes to Java interfaces injected / removed via add/removeJavascriptInterface only affect the next loaded page. That is, after you, say, added a new Java interface, you must do a page (re)load in order to make this interface actually available to the page. If you try to change injected interfaces configuration from onPageStarted, this again may or may not affect the page you are loading.
So if you want to do a cleanup, or prepare for navigating to a new page, it's better to use shouldOverrideUrlLoading, because it is called after the page has decided to navigate, but before any loading has started (just remember to return false from shouldOverrideUrlLoading so loading proceeds as usual).
If you want to modify freshly loaded page, e.g. insert your JavaScript code, use onPageFinished -- it is called after the resources of the new page have been loaded and parsed. But remember that it's too late to inject Java interfaces at this point, as they will only affect next loaded page.

History.js - sharing link of a AJAX loaded page

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.

Reload file.js every minute

I read (somewhere else on this site) you can't reload (or inject javascript) onto a page that is already rendered.
Is there any other way of doing this. For instance an iFrame?
I have a recent comment widget.js and I need to constantly get it to reload without reloading the whole page.
Any ideas?
edit: The site has recent comments on it and they are displayed via a recentcomment.js
Once the page is loaded it doesn't update itself unless you reload the page. I want it to update itself, a way to do this is to just reload the js file on the page, correct?
Why do you need to do this? It seems to me that there's probably a more appropriate solution to your problem.
But to answer it:
var elm = document.createElement("script");
elm.src = "Widget.js";
document.getElementsByTagName("head")[0].appendChild(elm);
Hope I didn't write any mistakes...
Rather than reloading the file, you can have all the implementation of the file contained in a function and then call the function every minute using the setTimeout() function.
Alternatively, if you want to reload it because the content of the file might have changed, it would probably be better to move that part of the code out to some external file and then use a function (running every minute with setTimeout()) to load the new content you need.
You can make cross-domain AJAX requests using certain methods, so you could make an AJAX request for the script file and parse it yourself. Parsing it yourself probably isn't an optimal solution, but it looks like you're dealing with a brain-dead service provider anyways.
Look at this guy's jQuery mod for an example:
http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
Once you get the data from the 3rd party, you could probably use some combination of regex and JSON parser to extract the comments.

are there any negative implications of sourcing a javascript file that does not actually exist?

If you do script src="/path/to/nonexistent/file.js" in an HTML file and call that in a browser, and there are no dependencies or resources anywhere else in the HTML file that expect the file or code therein to actually exist, is there anything inherently bad-practice about doing this?
Yes, it is an odd question. The rationale is the developer is dealing with a CMS that allows custom (self-contained) javascript files to be provided in certain circumstances. The problem is the CMS is not very flexible when it comes to creating conditional includes for javascript. Therefore it is easier to just make references to the self-contained js files regardless of whether they are actually at the specified path.
Since no errors are displayed to the user, should this practice be considered a viable option?
Well the major drawback is performance since the browser will try (hard) to download the file and your server will look for it. Finally the browser may download the 404 page instead - thus slowing down the page load.
If you have the script referred to in the <head> tag, ( not recommended for starters ), it will slow down the initial page-render time somewhat too.
If instead of quickly returning a 404, your site just accepts the connection and then never responds, this can cause the page to take an indefinite amount of time to load, and in some cases, lock up the entire user interface.
( At least that was the case with one revision of FireFox, I hope they've fixed it since I saw that happen ~2 years ago.* )
You should at least put the tags as low in the page order as you can afford to to remedy this problem.
Your best bet by far is to have one consistent no-op url that is used as a fill-in for all "doesn't exist" JavaScript files, that returns a 0-byte response with HTTP headers telling the UA to cache it till the cows come home, that should negate most your server<->client load penalties beyond the first hit ( and that should hardly hurt people even on ye-olde dialup )
*Lesson learned: don't put script-src references in head, especially for 3rd-party scripts hosted outside your machine, because then you can have the joy of having clients be able to access your website, but run the risk of the page being inoperable because of a bit of advertising JS that was inaccessible due to some internet weirdness. Even if they're a reputable-ish 3rd-party.
If your web server is configured to do work on a 404 error ("you might be looking for this", etc) then you're also causing unnecessary load on the server.
you should ask yourself why you were too lazy to test this yourself :)
i tested 1000 randomized javascript filenames and it took several nanoseconds to load, so no, it doesn't make a difference. example:
script src="/7701992spolsky.js"
This was on my local machine however, so it should take N * roundTripTime for the browser to figure out for remote servers, where N is the number of bad scripts.
If however, you have random domain names that don't exist, like
script src="http://www.randomsite7701992.com/spolsky.js"
then it will take a long f-in time.
If you choose to implement it this way, you could tune the web server that if the referenced JS file is not found, instead of 404, it could return a redirect (301) to an empty/default JS file.
If you are using asp.net you can look into using custom handlers (ASHX files).
Here's an example:
public class JavascriptHandler : IHttpHandler {
public void ProcessRequest (HttpContext context)
{
context.Response.ContentType = "text/plain";
//Some code to check if javascript code exists
string js = "";
if(JavascriptExists())
{
js = GetJavascript();
}
context.Response.write(js);
}
}
Then in your html header you could declare a file pointing to the custom handler:
src="/js/javascripthandler.ashx"

Categories

Resources