Forcing cache refresh after modifying head.js javascript calls? - javascript

I am using head.js and using the below file to initiate the javascript file calls:
<script src="/scripts/load.js" type="text/javascript"></script>
In the load.js file I have the following code:
head.js(
{livechat: "/scripts/livechat.js"},
{jquery: "http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"},
{jquerytools: "http://cdn.jquerytools.org/1.2.5/full/jquery.tools.min.js"},
{slider: "/scripts/jquery.nivo.slider.pack.js"},
{prettyphoto: "/scripts/jquery.prettyPhoto.js"},
{sliderfunctions: "/scripts/slidercode.js"},
{functions: "/scripts/functions.js"}
);
My problem is, even though I removed the livechat line, the chat box is still appearing on all my website pages unless I manually clear the browser cache. My concern is that I no longer utilize the livechat service and I do not want the visitors to be confused by seeing the livechat box appear but not function correctly.
Is there any way to tell head.js that there has been a change in the files being loaded and to refresh browser cache or something?

You could put something along the lines of this:
<script src="/scripts/load.js?date=123456789" type="text/javascript"></script>
Adding a query string to this file should trick the browser into thinking it's something it hasn't seen before.

Related

Valid Javascript: function document.onkeydown(...)?

I'm trying to set up a HikVision IP-based camera for some work I'm doing and it refuses to log in to the camera (the login button appears to do nothing).
The reason for this, when I break out the Chrome debugger console and investigate a bit deeper, is that the inbuilt login.js file (the one supplied by the camera) contains the code:
function document.onkeydown()
{
and the browser is complaining that the . is an invalid token in this context.
So my first question is simple: is this valid or invalid Javascript?
If it's invalid, I just have to track down the developer for a good talking to :-)
If it's valid, how do I get Chrome to stop complaining so that it can continue to process the rest of the file (including the definition of login function which is what would normally be called when I click on the login button)?
And, if it's not invalid and I don't want to wait around for a vendor fix, is it viable to just replace the login page and the Javascript file with local ones?
In other words, have those two files on my desktop (using 127.0.0.1) but have them reference all the other ones on the camera itself (192.0.0.whatever).
So, rather than accessing http://camera.com/page/login.asp which contains:
<script type="text/javascript" src="../script/login.js" />
<script type="text/javascript" src="../script/other.js" />
<script type="text/javascript" src="../script/again.js" />
I'd instead access file://login.htm, which would contain:
<script type="text/javascript" src="my_good_login.js" />
<script type="text/javascript" src="http://camera.com/script/other.js" />
<script type="text/javascript" src="http://camera.com/script/again.js" />
There is a problem with the firmware for some early HikVision cameras, in version 4.x.
The best solution is to upgrade the firmware to 5.2 where the Javascript code in the firmware is fixed.
This can be done with the SPD tool from HikVision itself.
However, if that's not an option, the scheme suggested should work. You just have to ensure that you correctly copy the errant firmware files off the camera onto your local box. That means:
Making an exact copy of the top-level page and errant login Javascript file locally (meaning on your host machine rather than the camera). This is probably as simple as just cut'n'pasting the browser source for both into new files(a).
Fixing the local copy of the errant login Javascript file, replacing document.onkeydown with the correct onkeydown.
Ensuring that you use the local top-level page from your browser rather than the on-camera one: this will ensure it uses the local login Javascript file.
Having that top-level page use your fixed login Javascript file: given it is a relative URL, that should work without change.
Ensuring the local top-level page accesses the other files on the camera: this will entail replacing the relative URLs with absolute ones.
(a) The only worrying possibility is the fact your current top-level page is an ASP one, whereas this process gets its HTML output fro creating the local top-level file. If the ASP file on the camera simply generates the same HTML each time, you'll be file.
However, if it's more complicated than that, you may have to do something tricky like extract the HTML from the camera each time with a script and massage it to change the URL accesses within a local page. Then access that local page from the browser. This could be automated but it's starting to get a little more difficult.
So, all in all, an upgrade to later fixed firmware is probably still the best option.

Force browser to refresh javascript code while developing an MVC View?

Pretty straight-forward, I'm developing an MVC5 application and have noticed (lately) that my Browser appears to be caching the JavaScript code I have on the view within #section Scripts { }.
Currently I am developing with Chrome and I have tried CTRL+F5 & CTRL+SHFT+R which reloads the page, but the alert() I uncommented within the javascript code is still rendering as commented. I also tried going to my localhost through Incognito Mode as well as other Browsers (Firefox, IE) and am getting the same behavior. This is my /Home/Index.cshtml View, which is the default View which loads when the application starts. I have also tried adding some extra HTML text into the page and again the new code is not taking effect/showing.
My current Chrome version is Version 41.0.2272.118 m if anyone has any ideas what might be going on?
UPDATE:
I have gone under the Developer Tools => General Settings in Chrome and checked [X] Disable cache (while DevTools is open) and then repeatedly (with DevTools still open) tried CTRL+SHFT+R and CTRL+F5 with the same results of before where my changes are not taking effect.
UPDATE 2:
With DevTools open I have also held the Refresh button down and tried Normal/Hard/and Empty Cache & Hard Reload options all with the same result. For simplicity of testing I added an alert in the below to dispaly as soon as the page loads (and currently no alert comes up):
$(document).ready(function () {
alert("Test");
// Other Code/Functions -- No Error showing in Console
});
If you are using Bundling from MVC, you have two options to disable caching:
Use BundleTable.EnableOptimizations. This instructs the bundling to minify and optimize your bundle even while debugging. It generates a hash in the process, based on the content of the script, so your customers browsers can cache this file for a long time. It will generate a whole different hash the next time your file changes, so your customers can see your changes. The downside is that your script will become unreadable and you won't be able to debug it, so this might not be your best option.
Use System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("url", true) to resolve your script's URL, the second parameter (true) is requiring a hash to be generated with the URL, thus, preventing caching from your browser when you change the file. This is exactly the same hash generated in the first option, but without minifying.
I created a small demo showing that the second option prevents caching from happening, the trick is getting the hash generated from your script's content without minifying your script.
I created a script file called myscript.js with this content:
$(document).ready(function () {
alert('a');
});
Then I added this to my BundleConfig.cs:
// PLEASE NOTE this is **NOT** a ScriptBundle
bundles.Add(new Bundle("~/bundles/myscripts").Include(
"~/Scripts/myscript*"));
If you add a ScriptBundle, you will get a minified response again, since ScriptBundle is just a Bundle using JsMinify transformation (source). That's why we just use Bundle.
Now you can just add your script using this method to resolve the script URL with the hash appendend. You can use the Script.Render
#Scripts.Render(System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/myscripts", true))
Or the script tag:
<script src="#System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/myscripts", true)"></script>
Either way will generate a URL with a hash to prevent caching:
After editing my file:
You might want to add a no_cache variable after your script url like:
<script src="js/stg/Stg.js?nocache=#random_number"></script>
If you manage to put a random number to the place i indicated, the browser will automatically download the latest version of the script after an F5
A quick trick that solves this problem consists of opening the script file in a new tab, then refresh it on this page.
If you happen to have Chrome dev tools open it will even refresh it there.
From dev tool you can even easily right click-open in new tab the script.

how should my site handle ocassionally missing javascript files gracefully?

Say I've got this script tag on my site (borrowed from SO).
<script type="text/javascript" async=""
src="http://edge.quantserve.com/quant.js"></script>
If edge.quantserve.com goes down or stops responding without returning a 404, won't SO have to wait for the timeout before the rest of the page loads? I'm thinking Chaos Monkey shows up and blasts a server that my site is depending on, a server that isn't part of a CDN and has a poor failover.
What's the industry standard way to handle this issue? I couldn't find a dupe on SO, maybe I'm searching for the wrong terms.
Update: I should have looked a bit more closely at the SO code, there's this at the bottom:
<script type="text/javascript">var _gaq=_gaq||[];_gaq.push(['_setAccount','UA-5620270-1']);
_gaq.push(['_setCustomVar', 2, 'accountid', '14882',2]);
_gaq.push(['_trackPageview']);
var _qevents = _qevents || [];
(function(){
var s=document.getElementsByTagName('script')[0];
var ga=document.createElement('script');
ga.type='text/javascript';
ga.async=true;
ga.src='http://www.google-analytics.com/ga.js';
s.parentNode.insertBefore(ga,s);
var sc=document.createElement('script');
sc.type='text/javascript';
sc.async=true;
sc.src='http://edge.quantserve.com/quant.js';
s.parentNode.insertBefore(sc,s);
})();
</script>
OK, so if the quant.js file fails to load, it's creating a script tag with ga.async=true;. Maybe that's the trick.
Possible answer: https://stackoverflow.com/a/1834129/30946
Generally, it's tricky to do it well and cross-browser.
Some proposals:
Move the script to the very bottom of the HTML page (so that almost everything is displayed before you request that script)
Move it to the bottom and wrap it in <script>document.write("<scr"+"ipt src='http://example.org/script.js'></scr"+"ipt>")</script> or the way you added after update (document.createElement('script'))
A last option is to load it via XHR (but this works only for same-domain, or cross-domain only if the CORS is enabled on a third-party server); you can then use timeout property of the XHR (for IE and Fx12+), and in the other browsers, use setTimeout and check the XHR's readyState. It's kind of convoluted and very non-cross-browser for now, so the option 2 looks the best.
Make a copy of the file on your server and use this. it will load your copy only if the one from the server has failed to load
<script src="http://edge.quantserve.com/quant.js"></script>
<script>window.quant || document.write('<script src="js/quant.js"><\/script>')</script>
To answer your question about the browser having to wait for the script to load before the rest of the page loads, the answer to that would typically be no. Typical browsers will have multiple threads processing the download of the page and linked content (CSS, images, js). So the rest of the page should be loaded, though the user's browser indicator will still show the page trying to load until the final request is fulfilled or timed out.
Depending on the nature of the resource you are trying to load, this will obviously effect your page differently. Typically, if you are worried about this, you can host all your files on a common CDN (or your website if it is not that highly trafficked), that way at least if one thing fails, chances are everything is failing and you have a bigger issue to contend with :)

Certain .js pages not loading in time

I have certain pages on my site that loads a good amount of JavaScript files. In the code below, edit_onload() is in script1.js. Typically all the scripts load fine and edit_onload fires successfully. On occasion it seems like script1.js isn't loading in time because edit_onload() errors with object expected. If you refresh the page everything will load fine.
My question is, shouldn't the <script> tag below wait for all of the .js files to load and then execute edit_onload()?
<script LANGUAGE="javascript" DEFER="true" for="window" event="onload">
<xsl:comment>
<![CDATA[
edit_onload();
]]>
</xsl:comment>
</script>
<script language="javascript" src="/_scripts/script1.js" defer="true"></script>
<script language="javascript" src="/_scripts/script2.js" defer="true"></script>
<script language="javascript" src="/_scripts/script3.js" defer="true"></script>
I think, an implementation of processing of deferred scripts is browser specific. For example, they can handle inline and external scripts in different queues. In general the 'defer' attribute is just a recommendation provided by a site developer for a user agent, but the user agent will not necessarily abide by the recommendation.
Also you should try using 'defer="defer"'. Can you move the call to the script1.js itself? Also you can periodically check an existence of a specific element moved to the end of the content being loaded and run the method only after the element is discovered.
BTW, you could possibly gain more control over script loading if you use a dynamic script loading metaphor (the link is just one of examples).

Lazyloading Google API not working

Here's the deal. I've tried a number of methods of lazy loading the Google Maps API JavaScript, and every time in do it, with any Lazy Loader I use, FireFox "blocks." It lazy loads just fine in Chrome.
What I mean by "blocks" is that the elements in the HTML don't display, and instead, the browsers spin trying to make a connection to download the Maps JavaScript.
The code follows. Put it in an HTML file and open it in your browser:
<html>
<head>
<script type="text/javascript" src="http://github.com/rgrove/lazyload/raw/master/lazyload.js"></script>
</head>
<body>
Open your console. Wait for "entering debugger..." message.<br />
You can't see me in FireFox, can you?
<script type="text/javascript">
// If I remove the `sensor` from the query string key and value,
// Google rejects the request and alert() does occur
LazyLoad.js("http://maps.google.com/maps/api/js?sensor=false", function() {
console.log("entering debugger...");
});
</script>
</body>
</html>
In Chrome, I see the "Open your console..." contents of the page, and the JavaScript is requested and downloaded, async, in the background.
In FireFox, the "Open your console..." contents never appear, and it hangs (status bar says "Read" from a Google DNS), never finishing or displaying the page contents.
Are you sure you need to write your own loader? What about using a previously tested implementation: Lazy Load
Are you trying to load Google Maps on demand? To load the API dynamically, pass a callback parameter, as shown on the Example
I think you'll need to rename your LazyLoad script, because it already exists. :) Speaking of which, it already exists, so why write it again?
If you just want to see how it's done, the source code is available.
Yeah, why reinvent the wheel. You seem to be using jQuery.
try this plugin:
Load image only when it is viewable?
Found a solution:
Check the URL:'http://maps.google.com/maps/api/js?sensor=true'
You would find main.js is being imported by it . A simple getScript for sensor=true will not give whole google object so next import also required.
var t=setTimeout(function(){
jQuery.getScript('http://maps.google.com/maps/api/js?sensor=true');
jQuery.getScript('http://maps.gstatic.com/intl/en_us/mapfiles/api-3/10/20/main.js');
},1000);
PS: Similar issue thread Lazy loading google map api

Categories