I'm having an issue with updating a web application in Chrome. It’s an ASPX site, but I don’t believe it’s relevant to this conversation. The issue is that our clients don’t get the latest programming in Chrome, because most of the time, it fails to release Javascript and CSS programming from memory, then proceeds to cause all kinds of mayhem while in use.
I tried placing this piece of code in the <head>, like many have suggested, but it doesn’t work all the time.
<script type="text/javascript">
function reload_js(par_src) {
src = $('script[src$="' + par_src + '"]').attr("src");
$('script[src$="' + par_src + '"]').remove();
$('<script/>').attr('src', par_src).appendTo('body');
}
reload_js("../../global/scripts/global_scripts.js");
reload_js("scripts/main.js");
reload_js("scripts/tabs/jquery.ui.core.js");
reload_js("scripts/tabs/jquery.ui.widget.js");
reload_js("scripts/tabs/jquery.ui.mouse.js");
reload_js("scripts/tabs/jquery.ui.sortable.js");
reload_js("scripts/tabs/jquery.ui.tabs.js");
reload_js("scripts/chat_room.js");
</script>
And I use this Javascript file to refresh my css's. One that I found here.
<script src="../../global/scripts/css_refresh.js" type="text/javascript"></script>
I'm scared that these methods cause unnecessary overhead, because they run every time a page is loaded.
Could one of you experts please tell me if this is the most efficient method for updating? Or perhaps recommend a better method to keep these files up to date?
Simplest way to fix this is to add an identifier to the script/style-files. Just add something like ?version=12 (and update the number for each release) then the browser will fetch the newest file. You can also use some sort of server-side date-option after the ?of course, to force a new fetch every day or similar.
Related
I'm trying to mock the date on a CefSharp browser by injecting MockDate and setting it to some fixed date before every other script runs. Every window object, on any frame, at any time, should only have access to the mocked date, so the ideal would be to internally redefine the JavaScript Date object, but I don't think CefSharp or probably even Chromium has this option. I'm also going to mock some other functions like setTimeout and Math.rand, to prevent the browser from having any side effects (this is part of a larger project whose aim is to be able to record/replay browsing activity), so messing with OS's time wouldn't solve it.
I considered using RegisterJsObject since it can actually overwrite existing globals, but I don't think there is a way to pass a JavaScript constructor.
What I've tried so far is to handle the FrameLoadStart event:
private static string Inject = File.ReadAllText("Inject.js");
private void ChromeBrowser_FrameLoadStart(object sender, FrameLoadStartEventArgs e)
{
e.Frame.ExecuteJavaScriptAsync(Inject);
}
Where "Inject.js" contains the mock date code. But I've noticed that, randomly, sometimes it'll work and sometimes it won't. I guess because the function is async and the javascript context sometimes haven't been created, since according to the documentations you shouldn't run scripts here. The documentation recommends handling OnContextCreated instead, but it only runs for the main frame, which wouldn't let me inject the code on any iframe. So I wonder if I have any alternative.
In case anyone else need this, the solution was to modify the actual C++ CefSharp code by adding a line to the end of CefAppUnmanagedWrapper::OnContextCreated:
frame->ExecuteJavaScript(CodeToInject, "something://something", 1);
This won't work if injected on the C# side, I believe because these calls are async so you may be injecting it too late, after scripts on the page have already run.
If you can edit HTML entry points then you can just add window.Date = MockDate before any other scripts. For example:
<html>
<body>
<script src="mockdate.js"></script>
<script>
window.Date = MockDate
</script>
<script src="myscript.js"></script>
</body>
</html>
So the idea is you can tune script loading order in your HTML. It can be done in any browser.
If you can not or do not want to edit HTML then it's much trickier. You could use CefLoadHandler in CEF C++ or its alternative in CefSharp.
UPD
Actually i'm not sure about CefLoadHandler. The reliable way would be to implement your own CefRenderProcessHandler But you already mentioned it. If it doesn't work then it's a bug in CefSharp or CEF C++ itself. In that case it would be better to write about it on http://magpcss.org/ceforum/
Once upon a time, there were many heated debate on <script> in <head> or <body>.
Many SO posts had already pointed out the best practice / rule of thumb is to place the <script> before end of <body>for not blocking the html parser, resulting faster first screen paint and quicker DOM access for client, and thus a better UX.
This must be a duplicate╰(‵□′)╯
Wait ... <script> can be deferred now, actually for quite a while !
Old posts said
deferred script may results JS dependency issues
No, it won't. It retains the order on execution immediately when the DOM gets parsed.
It doesn't work cross vendors
Yes, it once was, but today it's almost supported by all major browser vendors: http://caniuse.com/#search=defer, besides may have some problem with IE<10 as the comments point out.
However, the benefits it offers seem obvious, at least to me, as it downloads the script in parallel at earlier time(before start parsing the DOM), thus no need to request the script later and shortens the time it takes to bring the whole page interactive.
To be short, this question is similar to: Any good reason not to use
<head>
...
<script src='cdn/to/jquery' defer>
<script src='cdn/to/bootstrap' defer>
<script src='script/depends/on/jqueryandbootstrap' defer>
</head>
instead using this:
<body>
...
<script src='cdn/to/jquery'>
<script src='cdn/to/bootstrap'>
<script src='script/depends/on/jqueryandbootstrap'>
</body>
note: This might be an "ancient" topic with lots of discussions. However, as web technology moves really fast, browser vendors align better and more consistent with new web specs, many old stackoverflow answers may not keep up-to-date.
Yes, but only because you're using jQuery.
jQuery doesn't work with defer because it tries to fire as soon as the page becomes interactive. They can't fix it any time soon (I raised that bug over a year ago) because changing the ready behaviour to work with defer will break lots of components that rely on jQuery's ready event firing on interactive (i.e. before deferred scripts have finished loading).
If you're using a more modern framework (React, Angular 2, Polymer, Vue, or just about anything else) then go for it - or even go to the next step and use <script type=module in new browsers and a legacy bundle in <script nomodule defer... for IE.
As noted here you should take browser support into account, as some of them don't really support it. There are also some well known bugs in some versions like this one in IE<=9.
If your goal is not to support old browsers (find full support list here) then there is no real reason for not picking defer today.
I'm doing a couple of things with jQuery in an MTurk HIT, and I'm guessing one of these is the culprit. I have no need to access the surrounding document from the iframe, so if I am, I'd like to know where that's happening and how to stop it!
Otherwise, MTurk may be doing something incorrect (they use the 5-character token & to separate URL arguments in the iframe URL, for example, so they DEFINITELY do incorrect things).
Here are the snippets that might be causing the problem. All of this is from within an iframe that's embedded in the MTurk HIT** (and related) page(s):
I'm embedding my JS in a $(window).load(). As I understand it, I need to use this instead of $(document).ready() because the latter won't wait for my iframe to load. Please correct me if I'm wrong.
I'm also running a RegExp.exec on window.location.href to extract the workerId.
I apologize in advance if this is a duplicate. Indeed - after writing this, SO seems to have a made a good guess at this: Debugging "unsafe javascript attempt to access frame with URL ... ". I'll answer this question if I figure it out before you do.
It'd be great to get a good high-level reference on where to learn about this kind of thing. It doesn't fit naturally into any topic that I know - maybe learn about cross-site scripting so I can avoid it?
** If you don't know, an MTurk HIT is the unit of work for folks doing tasks on MTurk. You can see what they look like pretty quick if you navigate to http://mturk.com and view a HIT.
I've traced the code to the following chunk run within jquery from the inject.js file:
try {
isHiddenIFrame = !isTopWindow && window.frameElement && window.frameElement.style.display === "none";
} catch(e) {}
I had a similar issue running jQuery in MechanicalTurk through Chrome.
The solution for me was to download the jQuery JS files I wanted, then upload them to the secure amazon S3 service.
Then, in my HIT, I called the .js files at their new home at https://s3.amazonaws.com.
Tips on how to make code 'secure' by chrome's standards are here:
http://developer.chrome.com/extensions/contentSecurityPolicy.html
This isn't a direct answer to your question, but our lab has been successful at circumventing (read hack) this problem by asking workers click on a button inside the iframe that opens a separate pop-up window. Within the pop-up window, you're free to use jQuery and any other standard JS resources you want without triggering any of AMT's security alarms. This method has the added benefit of allowing workers to view your task in a full-sized browser window instead of AMT's tiny embedded iframes.
I am bulding a webpage using xPages and I am making constant changes to script and design, this include both server and client javascript , stylesheet and image changes.
Each time I change a javascript or stylesheet I want to see my changes in the webbrowser and I also want my users to get the latest changes when they access the webpage.
I know I can use Shift-Reload, or CTRL-reload and clear my webbrowser cache. and I also know that I can change the objects expiration date, but I want a smoother and better controlled way to do this.
Looking for any kind of best practice for doing this.
Thanks
Thomas
In the xsp.properties file for the application or on the server for server wide use you can set xsp.application.forcefullrefresh=true. The xsp.properties file documentation says:
# Application refresh
# When this property is set to true, then a full application refresh is requested when
# the design of a class changes (means that all the data are discarded in scopes).
# xsp.application.forcefullrefresh=false
The new XSP Portable Command Guide says "This property was introduced in Notes/Domino 8.5.3. It is set to false by default and is particularly useful during the development phase of an XPages application."
I have not fully tested this behavior but it sounds promising. You could/should of course only set it to true WHILE you make the changes. once stable, set it back.
/Newbs
Adding to Ferry's answer and your comment;
Instead of "?dummy=randomvalue", you can use "?version=2.1". So it will be cached but when you change design, you can just increase the version.
There's a problem with this approach as some proxy servers won't cache anything with query params. Better to rename the file directly, adding date or version number to it. It will always work.
To disable caching temporarily use Fiddler2. It's easy to enable and disable in one place across any web client. As well as added benefits for the http request tracking features.
To fully disable any caching add url + '"?dummy=" + #Unique();' to every url to javascript or image files...
The way I am reading this question is that you want every change you make to appear immediately on the client's browser or client. Are you really sure you want to do this? It sounds like you are not doing any testing so any typos, bugs, crashes, etc will be passed on to your users. Sounds like a bad plan to me. I hope I am wrong and that you are using a template and pushing only your fully tested changes up to an production version instead of making the changes in the production version.
I would just put out a schedule of when changes are going to be pushed up to production and let the users reload their browser or client at that time. Either that or do it during off hours and when they next log on, they get the newest changes.
Adding to Ferry's answer and your comment;
Instead of "?dummy=randomvalue", you can use "?version=2.1". So it will be cached but when you change design, you can just increase the version.
maybe you could look at how domino can control caching of url's.
http://www.ibm.com/developerworks/lotus/library/ls-resp_head_rules/
NEwbs answer is a good one but it is useful to note that in Firefox there is a very useful plug in called "web developer" from Chris Pederick that allows you to disable the cache.
http://chrispederick.com/work/web-developer/
The other really useful one is Firebug which is just amazing - It makes any HTML work much easier
https://addons.mozilla.org/en-US/firefox/addon/firebug/
I did found another solution by putting my css and js in a theme it is easy to just rename the files.
as described here
http://goo.gl/vFTii
Why do not we use the window.location.reload()...
Which does the same like ctrl+F5
It reloads the page, which is similar to context.reloadpage
I am writing some bookmarklets for a project that I am currently working on and I was wondering what the best practice for writing a bookmarklet was. I did some looking around and this is what I came up with
javascript:void((function()
{
var%20e=document.createElement('script');
e.setAttribute('type','text/javascript');
e.setAttribute('src','http://someserver.com/bookmarkletcode.js');
document.body.appendChild(e)
})())
I felt this is nice because the code can always be changed (since its requested every time) and still it acts like a bookmarklet. Are there are any problems to this approach ? Browser incompatibility etc? What is the best practice for this?
That bookmarklet will append a new copy of the script to the document every time it is run. For long-lived pages (e.g. Gmail), this could add up to a lot of memory usage, and if loading your script has side effects, they’ll occur multiple times. A better strategy would be to give your script an id, and check for existence of that element first, e.g.:
var s = document.getElementById('someUniqueId');
if (s) {
s.parentNode.removeChild(s);
}
s = document.createElement('script');
s.setAttribute('src', 'http://example.com/script.js');
s.setAttribute('type', 'text/javascript');
s.setAttribute('id', 'someUniqueId');
document.body.appendChild(s);
N.B. another alternative is to keep the existing script if it’s already in the document. This might save some server traffic if your bookmarklet is used frequently between page reloads. The worst case is that someone is using an older version of your script for a while; if you don’t expect it to change often, that might be fine.
Looks OK. But if your js file is already cached, it will not be requested every time. So you'd need it to append '?' + new Date() to your src attribute to ensure it is requested every time.