If this is a duplicate question I am sorry, it seems basic enough but could not find a proper answer.
The only way I have found so far to capture the browser window close event from actionscript/flash is actually to capture the event in javascript, and then use a javascript/flash data passing from the javascript callback.
Something around those lines:
window.onbeforeunload = clean_up;
function clean_up()
{
var flex = document.${application} || window.${application};
flex.myFlexFunction();
}
</SCRIPT>
and the flash part:
import flash.external.ExternalInterface;
ExternalInterface.addCallback("myFlexFunction",cleanUp);
public function cleanUp():void{
//your flash code here
}
Is this the proper way ?
Are there other alternatives ?
You can never catch the window close event from pure flash. That said, as far as I know, this is the proper way to handle this.
Related
My requirement is that I need to call some API after close tab from browser in Javascript.
I have tried below code which almost everyone suggest, but that is not working every time. I have tried every possible way with below code:
window.onbeforeunload = function () {
callClose();
return;
};
function callClose() {
// API call
}
I need proper reliable solution for this. Can anyone help me on this, I am stuck here.
I currently am working on a bookmarklet that opens an iframe, and sets up a communication of postMessage back and forth. That all works fine.
However, seemingly because the bookmarklet is being loaded as an anonymous function, the listeners are multiplying if I run the bookmarklet more than once on a page.
Is there some sort of way to keep track of these addEventListeners so that they don't double-up?
Do I need to define the rp_receive_message outside of the anonymous function?
Here's an example of the code:
var rp_receive_message = function (e) {
var response = e.data;
console.log("got message with "+ response);
};
if (window.addEventListener) {
window.addEventListener('message', rp_receive_message, false);
} else {
window.attachEvent('onmessage', rp_receive_message);
}
var s1 = window.document.createElement('iframe');
s1.setAttribute('src', 'http://mydomain.com/iframe.html');
s1.setAttribute('id', 'testiframe');
s1.setAttribute('width', '700');
s1.setAttribute('height', '550');
s1.setAttribute('frameBorder', '0');
s1.setAttribute('onload', 'this.contentWindow.postMessage(window.location.href, "http://mydomain.com/iframe.html");');
document.getElementById('container').appendChild(s1);
Probably this will solve the problem:
window.onmessage = rp_receive_message;
As you suggest, the code below might be enough by itself. I don't know if addEventListener and attachEvent will add the same function multiple times, but I wouldn't at all be surprised if they will. I suggest just testing it.
window.rp_receive_message = function(){...}
If you dislike either solution, you've got to set up a global variable, which hardly seems any different or greatly superior to above. The global can be a simple boolean to check if the event has been attached, or it can be a list of attached events that you update yourself. AFAIK, and I'm pretty sure, there is no native JS solution to get a list of event listeners have been attached to a particular event. Libraries such as jQuery maintain lists and let you read them; and possibly have other techniques that are elegant solutions to your general problem.
I hope I did my homework well, searching the Internets for the last couple of hours and trying everything before posting here, but I'm really close to call it impossible, so this is my last resort.
I want a simple thing (but seems like hard in JavaScript):
Click button -> Open Window (using window.open)
Perform an action in the popup window and return the value to parent (opener)
But I want to achieve it in a systematic way, having a callback defined for this popup; something like:
var wnd = window.open(...)
wnd.callback = function(value) {
console.log(value);
};
I've tried defining the callback property in popup window JS code:
var callback = null;
Unfortunately, that does not work, as...
$('#action').click(function() {
console.log(callback);
});
... returns just that "null" I set initially.
I've also tried setting the callback in a parent window after window load (both thru window.onload=... and $(window).ready()), none worked.
I've also tried defining some method in child window source code to register callback internally:
function registerCallback(_callback)
{
callback = _callback; // also window.callback = _callback;
}
But with the same result.
And I don't have any more ideas. Sure, it would be simple setting the value using window.opener, but I'll loose much of a flexibility I need for this child window (actually an asset selector for DAM system).
If you have some ideas, please share them.
Thank you a million!
HTML5's postMessage comes to mind. It's designed to do exactly what you're trying to accomplish: post messages from one window and process it in another.
https://developer.mozilla.org/en/DOM/window.postMessage
The caveat is that it's a relatively new standard, so older browsers may not support this functionality.
http://caniuse.com/#feat=x-doc-messaging
It's pretty simple to use:
To send a message from the source window:
window.postMessage("message", "*");
//'*' is the target origin, and should be specified for security
To listen for messages in a target window:
window.addEventListener
("message", function(e) {
console.log(e.data); //e.data is the string message that was sent.
}, true);
After few more hours of experiments, I think, I've found a viable solution for my problem.
The point is to reference jQuery from parent window and trigger a jQuery event on this window (I'm a Mac user but I suppose, jQuery has events working cross-platform, so IE compatibility is not an issue here).
This is my code for click handler on anchor...
$(this).find('a[x-special="select-asset"]').click(function() {
var evt = jQuery.Event('assetSelect', {
url: 'this is url',
closePopup: true,
});
var _parent = window.opener;
_parent.jQuery(_parent.document).trigger(evt);
});
... and this is the code of event handler:
$(document).bind('assetSelect', function (evt) {
console.log(evt);
});
This solution is fine, if you don't need to distinguish between multiple instances of the asset selection windows (only one window will dispatch "assetSelect" event). I have not found a way to pass a kind of tag parameter to window and then pass it back in event.
Because of this, I've chosen to go along with (at the end, better and visually more pleasant) solution, Fancybox. Unfortunately, there is no way - by default - to distinguish between instances either. Therefore, I've extended Fancybox as I've described in my blog post. I'm not including the full text of blog post here, because is not the topic of this question.
URL of the blog post: http://82517.tumblr.com/post/23798369533/using-fancybox-with-iframe-as-modal-dialog-on-a-web
Is there a way to run a function only if event.preventDefault() is called on an event (by another unknown function). This is for a jQuery plugin, so I don't have any knowledge of what other parts of the page might be doing. I've tried this:
Event.test = Event.preventDefault;
Event.preventDefault = function () {
alert('Success');
this.test();
}
but it doesn't work... just behaves as normal, with no errors.
Conversely, I want the opposite too... to call a function only if event.preventDefault() isn't called. In effect, to add a function to the default action for an event. Any ideas? Is all this at all possible?
Edit: Based on the comment, I've got a solution to the first problem: http://jsfiddle.net/nathan/VAePB/9/. It works in Chrome (alerts function preventDefault() { [native code] }, but IE alerts undefined. So IE won't let me define Event.prototype.test, but it will let me redefine Event.prototype.preventDefault. Weird. I'm sure I can come up with a solution to the the second problem based on this one if I can just get it to work in IE.
I'm not sure I've understand. Can't you just use event.isDefaultPrevented() like this
For the first problem, try something like this:
oldPreventDefault = Event.prototype.preventDefault;
Event.prototype.preventDefault = function() {
//do stuff
oldPreventDefault.call(this);
}
I don't know if that will work, but it might be worth a shot.
For the second problem, I would try something similar to live event handling. Put a listener on a parent element (i.e. body or a top-level div). If you can get your hook into preventDefault as noted before, you can use that to set a flag. If the event bubbles up to that element and your flag isn't set, do your extended behavior. Though this won't work with all events, since not all events bubble. Another way to tackle this problem might be to delay execution until the current stack has finished using setTimeout(0,...) and then checking the flag.
I'm looking for a way to check within pageLoad() if this method is raised during load event because of a postback/async postback or because of being loaded and access the first time.
This is similar to Page.IsPostback property within code behind page.
TIA,
Ricky
One way you could do that is to wire up an Application.Load handler in Application.Init, then have that handler unbind itself after running:
Sys.Application.add_init(AppInit);
function AppInit() {
Sys.Application.add_load(RunOnce);
}
function RunOnce() {
// This will only happen once per GET request to the page.
Sys.Application.remove_load(RunOnce);
}
That will execute after Application.Init. It should be the last thing before pageLoad is called.
#Darren: Thanks for the answer. I had tried to create pageLoad with event argument ApplicationLoadEventArgs as parameter (see below). However according to this:
The load event is raised for all postbacks to the server, which includes asynchronous postbacks.
As you have indicated, the isPartialLoad property does not cover all postback scenarios. It'll be nice if the event argument also contain isPostback property.
function pageLoad(sender, arg) {
if (!arg.get_isPartialLoad()) {
//code to be executed only on the first load
}
}
#mmattax: I'm looking for property that can be called from client-side (javascript).
What you can do is wire up to the load event of the Sys.Application class. you can then use the isPartialLoad property of the Sys.ApplicationLoadEventArgs class. I believe that would let you know if you are in a async postback or not.
To know if you are in a post back, you'll have to handle that in server side code and emit that to the client.
You could have a hidden input that you set to a known value on the server side if it's a postback/callback - and your javascript could check that value.
That said, I really hope that there's a client-only solution for this.
Edit: #mmattax - I believe he's looking for a client-side solution - the JavaScript equivalent of that.
You can still use Page.IsPostback during an async call.
Application.Init is probably a more appropriate event to use, if you only want the code to execute on the first load.
#Dave Ward: This normally would work. However, the code is to attach event on behavior object. Because the creation of behavior object happens during Application.Init, attaching to that event will lead to unpredictable behavior.
It will be nice if there is PostInit event.
#Dave Ward:
The use of RunOnce method works perfectly. This solve my problem without having the workaround to check first if handler already exist before attaching to an event.
I'll mark your answer as an accepted answer. Thanks again.
Here's our Ajax equivalent to isPostback which we've been using for a while.
public static bool isAjaxRequest(System.Web.HttpRequest request)
{//Checks to see if the request is an Ajax request
if (request.ServerVariables["HTTP_X_MICROSOFTAJAX"] != null ||
request.Form["__CALLBACKID"] != null)
return true;
else
return false;
}