I am using a JavaScript to track the activities of users on my page upon unloading that very page. Consider the following simplified dummie-script to simulate what I am doing on unload:
$(window).unload(function() {
$.get("http://www.google.de/images/srpr/logo3w.png");
});
The image URL in that case serves as a holder for tracking data.
The image is requested in some browsers (e.g. Firefox 3) and isn't loaded in others (e.g. Firefox 6) when closing the browser window.
Probably isn't the way it should be done; anyhow I would like to hold on to it as long as I could make a statement on how reliable the unload-event is.
Any experiences on this?
I have some experience with that and I would recommend a slightly different approach like this:
$(window).unload(function() {
new Image().src = "http://www.google.de/images/srpr/logo3w.png?timestamp="
+ new Date().getTime();
});
The challenge is that if you are making an AJAX-call at unload, you should use synchronous mode. With normal async-mode, it may not succeed at all (for instance in Chrome).
But in this case, a trick using image is just as reliable because the communication is one way only. That works for GET but if you need to POST something then sync-mode is the only option.
Related
I'd like to run some external JavaScript with a time restriction, so that if it takes more than N seconds it will be stopped.
Some browsers, e.g. Firefox, already do this with a dialog that asks if you want to allow a script to keep running. However, I'm looking for a bit more:
I want to set my own time limit rather than use the browser's default (e.g., I believe Chrome's is much longer than Firefox's).
I want to be able to do this on a per-script basis, not per-page. One page may contain multiple scripts that I want to restrict in this way (hence my idea to use <iframe> elements).
I was thinking it would be very convenient if there were simply an attribute I could attach to an <iframe>—e.g., something like js-time-limit="5000" (I just made that up)—but I haven't been able to find anything like that.
Is this possible? To put a configurable time limit on JavaScript execution in a browser?
If the iframe is doing computation work and doesn't need to access the DOM, then use web workers: https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers
Here is also a library that can abstract away the hard parts for you! http://adambom.github.io/parallel.js
Important parts:
Dedicated Web Workers provide a simple means for web content to run scripts in background threads.
If you need to immediately terminate a running worker, you can do so by calling the worker's terminate() method: myWorker.terminate();
Browser compatibility
Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
3 3.5 (1.9.1) 10 10.60 4
For posterity: my original goal was to allow users of a website to submit JS code and run it in the background with a time limit so that, e.g., infinite loops don't wreak havoc on the CPU.
I created a library called Lemming.js using the approach Joe suggested. You use it like this:
var lemming = new Lemming('code to eval');
lemming.onTimeout(function() {
alert('Timed out!');
});
lemming.onResult(function(result) {
alert('Result: ' + result);
});
lemming.run({ timeout: 5000 });
You can check out the GitHub repo for more details.
I need to be able to make an event such that every time a user loads a new page and closes firefox, I need it to call a method in my C# application that takes care of maintaining the user model. I know for sure I need to create some type of firefox extension where I use javascript to check such an event. However, I have no idea how I am going to integrate my C# application with the firefox extension. Can someone provide me with some guidance?
I'll help you out with the parts of the question that I'm familiar with (Javascript based add-ons), and offer some suggestions for the other parts. Here goes nothing!
Add-ons
Firefox add-ons easily provide the tools you need to detect page loads and opening / closing firefox.
To detect page loads you can register a listener to the DOMContentLoaded event in window.
window.addEventListener("DOMContentLoaded", function(event){
var url = event.originalTarget.location.href;
alert("Oh yeah, a document is loading: " + url);
}, false);
Alternatively, you can register a nsIWebProgressListener to listen for location changes. This probably closer to what you want, since DOMContentLoaded is also triggered for iframes.
var listener = {
//unimplemented methods (just give functions which do nothing)
onLocationChange: function(aWebProgress, aRequest, aLocation){
var url = aLocation.asciiSpec;
alert("Oh yeah, a the location changed: " + url);
}
};
gBrowser.addTabsProgressListener(listener);
To detect firefox open / close you need to first understand how firefox add-ons work with respect to multiple windows. When a new window of firefox is launched, you basically have 2 separate copies of your code running. So, if you care about firefox windows being opened and closed you can simply do:
window.addEventListener("load", function(event){
alert("Looks like you just opened up a new window");
}, false);
window.addEventListener("unload", function(event){
alert("Awh, you closed a window");
}, false);
But, most likely you want to detect opening / closing firefox as an entire application. This is achieved using a code-sharing mechanism called Javascript Modules. Javascript modules are loaded just once for the lifetime of the application. So, they enable you to share information between windows. Simply counting the number of windows opened and closed should be sufficient for this functionality.
var EXPORTED_SYMBOLS = ["windowOpened", "windowClosed"];
var windowsOpened = 0;
function windowOpened(){
if( windowsOpened === 0) {
alert("The first window has been opened!");
}
windowsOpened++;
}
function windowClosed(){
windowsOpened++;
if( windowsOpened === 0) {
alert("The last window has been closed!");
}
}
Then you can simply attach the aforementioned event handlers to call these 2 methods from their corresponding load and unload events.
So, this is all great and everything, but now you have to twiddle with the details of getting a baseline Firefox add-on setup. Fortunately, Mozilla has provided a handy Addon Builder to ease this. All the code about (except the Javascript module) should be placed in the ff-overlay.js file (assuming you use the linked builder).
C# communication
I'm a little less knowledgeable about the interprocess communication with C#. However, maybe I can point you in the right direction and let the smart people at SO fill in the rest.
I believe COM Objects are a method of communication between processes on Windows. So, you could build in a Binary Component to your add-on to perform the communication. However, as far as I understand it, setting up binary components is much more difficult than a standard javascript-based add-on. Either way, Mozilla provides a guide for setting it up in Visual Studio.
If you want to stay away from binary components you are left with the javascript enabled components of the SDK. This includes socket communication, files, pipes, a sqlite database etc. This SO question addresses exactly the question you're asking. If it were me, I would choose them in this order.
Sqlite Database
Named Pipes
Sockets
(1) because there is a lot of code samples available for this, and would be easy to implement on both sides. (2) because this would be the way I'd implement IPC if I were given full control of both sides of the application. (3) is last because I hate that crap (maybe I'm biased from Distributed Systems in college).
tl;dr
The page load stuff should be pretty simple. Check out the Addon Builder to get going with a FF addon, and here to see about detecting page loads.
The C# communication is doable, and addressed in this SO Question. I'd do it with a sqlite database for ease if it were me.
I used jQuery Address several times to support the back button in small asynchronous applications.
When all the AJAX requests do the same thing (that is, requesting a page asynchronously and replace an HTML element with the request) the implementation can be easy.
When the AJAX requests might do different things, let's say open an overlay in one case and change the content of the page entire page in another case, things become messy.
I ended up with some really crappy code for the fact that I had to go through a lot of if statements to analyze the hash value (#/somepage/someotherpage).
I always repeated to myself: there has to be a better way to do this.
Has anybody went through the same problem and can suggest a solution?
If not, check out my idea and tell me what you think.
My idea is to create an object which emulates the window.history object, but only for AJAX history, let's call it "ajaxhistory".
Each time a page is requested asynchronously something like this happens:
ajaxhistory[i] = {
url: 'here the url',
type: 'overlay'
otherusefulinfo: 'whatever'
}
i++
So, for example:
if(moving back or forward){
if(currenturl == ajaxhistory[i-1].url){
// i'm going back
// i'm able to know what type of action i should take thanks to
// ajaxhistory[i-1].type and ajaxhistory[i-1].otherusefulinfo
}
}
I like this idea because it would make my code much easier to read, mantain and change.
Suppose then I want to add new functionality... I can add a new type and I work with that, while normally I should edit a lot of crappy if statements.
What do you think? Would there be problems from a performance point of view?
Check out this work by Ben Alman
http://benalman.com/projects/jquery-bbq-plugin/
He has a plugin to help support back button.
Hope this is useful.
Bob
You can use html5 feature:
window.history.pushState({type: 'overlay'}, title, url), where first param is JS object.
You can access this object like that:
window.onpopstate = function(event) {
alert( event.state.overlay);
}
For more information, check https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history
So - I've been using this method of file uploading for a bit, but it seems that Google Gears has poor support for the newer browsers that implement the HTML5 specs. I've heard the word deprecated floating around a few channels, so I'm looking for a replacement that can accomplish the following tasks, and support the new browsers. I can always fall back to gears / standard file POST's but these following items make my process much simpler:
Users MUST to be able to select multiple files for uploading in the dialog.
I MUST be able to receive status updates on the transmission of a file. (progress bars)
I would like to be able to use PUT requests instead of POST
I would like to be able to easily attach these events to existing HTML elements using JavaScript. I.E. the File Selection should be triggered on a <button> click.
I would like to be able to control response/request parameters easily using JavaScript.
I'm not sure if the new HTML5 browsers have support for the desktop/request objects gears uses, or if there is a flash uploader that has these features that I am missing in my google searches.
An example of uploading code using gears:
// select some files:
var desktop = google.gears.factory.create('beta.desktop');
desktop.openFiles(selectFilesCallback);
function selectFilesCallback(files) {
$.each(files,function(k,file) {
// this code actually goes through a queue, and creates some status bars
// but it is unimportant to show here...
sendFile(file);
});
}
function sendFile(file) {
google.gears.factory.create('beta.httprequest');
request.open('PUT', upl.url);
request.setRequestHeader('filename', file.name);
request.upload.onprogress = function(e) {
// gives me % status updates... allows e.loaded/e.total
};
request.onreadystatechange = function() {
if (request.readyState == 4) {
// completed the upload!
}
};
request.send(file.blob);
return request;
}
Edit: apparently flash isn't capable of using PUT requests, so I have changed it to a "like" instead of a "must".
(Spawned from a comment on the original question, per askers's suggestion.)
Plupload is one of the newest kids on the block and it uses the best method available (HTML 5, Flash, Gears, Silverlight): http://plupload.com/
I have previously used flash based ones such as http://www.webresourcesdepot.com/open-source-flash-uploader-multi-bit-shift/. They work ok and being only dependent on flash should work on most computers. I haven't found a reliable way of doing it with js alone but flash could be controlled with js - especially if you write your own.
hope this helps.
Is it possible to disable AJAX without disabling JavaScript completely?
If you are using Firefox, you could accomplish this with GreaseMonkey. (https://addons.mozilla.org/en-US/firefox/addon/748)
GM is a framework for applying scripts to some or all of the pages you visit. I have GM scripts that disable google-analytics downloads (because they slow things down), and which disable google-click-tracking on google result pages (because it bothers me that they are doing that).
Here is my google-click disable script:
// ==UserScript==
// #name Google Clk
// #namespace googleclk
// #description Disable Google click tracking
// #include http://*google.com/*
// ==/UserScript==
// Override google's clk() function, which reports all clicks back to google
unsafeWindow.clk = function(url) {} // { alert(url); } // I use this to test.
By doing something similar with XMLHttpRequest (and other functions) you can effectively disable them. Of course, you may completely break the page by doing this, but you already knew that.
You can replace the browser tool to make AJAX (XMLHttpRequest object) with your own that does nothing.
XMLHttpRequest = function(){}
XMLHttpRequest.prototype = {
open: function(){},
send: function(){}
}
Be sure that your replacement code executes before any AJAX call.
This will work for any browser that implement AJAX through the XMLHttpRequest object but will not work for IE. For IE, you may have to overload the CreateObject() function if possible...
In IE this can be done with: Tools -> Internet Options -> Advanced Tab -> Scroll down to Security -> Uncheck 'Enable Native XMLHTTP Support'.
http://msdn.microsoft.com/en-us/library/ms537505%28v=vs.85%29.aspx
AJAX is simply the usage of the XMLHttpRequest function in Javascript. Depending on your browser, you may be able to lock down access to this function through your security settings.
At least with Firefox, you could disable it either through using a custom Extension.
This is a late comment on a question that has already been answered, but for the benefit of people coming in from Google:
With the Tab Permissions extension for Firefox you can disable JavaScript for a particular tab (as opposed to globally for all tabs) with a right-click context menu. I configured the "Permissions" menu item to toggle "Redirect" and "JavaScript," so if I stumble onto a page that has annoying refreshes and AJAX, I can quickly and easily shut down the bandwidth activity of the misbehaving tab without affecting the JavaScript on my other open tabs.
Additionally to the Firefox suggestion, you can do it in IE as a side-effect of disabling ActiveX. Also on IE7+ you have to disable the ‘Native XMLHttpRequest’ option.
No more than you can disable any other function - there may be some kludges or hacks to be found that could interfere with or break javascript, but we would hope not to find such vulnerabilities.
I'll take a wild stab in the dark and guess that you're trying to stop Ajax in untrusted user input of some kind? Your best bet in that case would be to avoid over-specifying your search parameters by mentioning Ajax, rather, search for 'sanitize javascript', 'user javascript safe'... that kind of thing.
No. AJAX is just a particular use of javascript.
If you could block the particular function call back to the server you might be able to do it, but you would probably have to edit your browser.
I assume you want to do this from the client end... Can you list some more specific goals? What is the expected outcome?