I have a main program (some sort of testing control panel) that runs another program in an IFrame. In some sorts, this is similar to Storybook. The reason to have an IFrame is to provide some separation between the program that is tested (which may do what it wants with its DOM) and the host w/ the control panel = buttons & co.
I was surprised to observe that if I have in the IFrame a dropdown, and I click somewhere but OUTSIDE that IFrame => the dropdown closes. So practically the code in the IFrame has reacted to an event that happened in the parent window. (NOTE: the page in the IFrame comes from the same domain).
This is something that I don't bothers me. Any ideas why this happens and what can I do to avoid this? So I'd like the code in the IFrame to stop receiving/reacting events that correspond to actions that I do outside the IFrame.
Related
For some interactive graphics we are using canvas in our HTML page. Inside the canvas we have "link-like" controls to link users to external resources.
Because of canvas, we do NOT use <a href=""> tag, but we are opening new browser tab via JS code, like this:
this.pixiLayout.App.renderer.view.addEventListener('click', () => {
if (this.pixiLayout.externalUrl) {
window.open(this.pixiLayout.externalUrl, '_blank');
}
});
The problem:
Google Analytics(front end) show us much more clicks than actual "page views" analytics from third party resources, up to 10-20 times.
It means that users clicked on the link(and it recorded by GA), but by some reason, link was not opened, or opened but not loaded in a new tab.
I know about ad/pop-ups blockers. It could be a case for some percentage of users. But it is not a case for 90% of users, like we have.
And we could not reproduce this behaviour on any device we own.
Question:
Could it be caused by normal browser policy or restriction that could cause a blocking of new tab like in our case?
Could it be like "new feature" of modern browsers I do not know about yet?
Ok, the issue was in our own code. Event firing of GA(we use custom events) was implemented in the different place of the code than an actual action - window.open(). They were supposed to be called on the same user action - user click. But it was not a case, specially for mobile devices. When user tapped on that interactive, link-like control and moved finger up or down(for scrolling), it fired custom event responsible for tracking "the click". But actual "click" event is not fired in this case.
Conclusion: never ever do an actual action in one place and "collect analytics of that action" in another place of the code.
I've got dialog that I wrote and it closes when clicking outside (no overlay/backdrop).
It works nicely unless there's an iframe, in which case my listener on outside clicks is never called.
Here is a JSBIN to illustrate the problem. (http://jsbin.com/vuneyopedu/edit?js,console,output)
To briefly explain in the below screenshot:
Clicking RED Dialog Increments.
Clicking Outside Dialog (YELLOW and GREEN) should Decrement but only YELLOW works.
The event listener for outside clicks is never called when clicking iframe (GREEN)
Question is - How do I make clicking anything outside the RED square (specifically clicking the iframe) decrement the number. (or close the dialog, in the "real" world)
How about binding event to iframes' document.
iframes = document.getElementsByTagName('iframe');
iframesArray = Array.prototype.slice.apply(iframes);
iframesArray.forEach(function(frame) {
frame.contentWindow.document.addEventListener('click', function() {
inc();
}, true);
});
The correct approach here is to use a modal and one of the strongest use-cases for the modal. By design modals prevent clicks from falling through to elements below hence there is no need to handle side effects like your iframe issue or e.stopPropagation() or anything else. It also makes positioning very clean.
As a side note, the currently accepted answer is a very poor approach since it relies on adding an event handler inside the iFrame, then binding that onto the parent container window. This is wrong on many levels: no separation of concerns, iframe from different domains will be blocked due to CORS, iframe will register with any and all parents even when not needed, etc.
I have an issue where a form is embedded in an iframe and after the form is submitted, the iframe is deleted from the DOM. Immediately after the form is deleted (the form was the last thing to have focus) I am unable to detect events that are bound to the root window element.
The frame is being loaded from a separate domain, although it does not matter for this example, it only matters that I have no control over the scripts on that page.
I understand that I cannot detect DOM events in the iframe, but all events are lost until the user clicks back on the DOM after iframe removal. This happens in both Firefox and Chrome. IE appears to return focus back to the original DOM as expected. I have not tested in other browsers.
$(window).keydown(function(e){
console.log (e.keyCode);
});
var $iframe = $("<iframe src='www.example.com'>");
$("body").append($iframe);
window.setTimeout(function(){
$iframe.remove();
}, 1000);
(The code above is just an example, i have included a working codepen to illustrate further- http://codepen.io/anon/pen/WQroqe)
To use the codepen -
Click the "click to load iframe button".
Make sure you click in the iframe so it has focus
After the iframe deletes, type anything and notice the DOM does not log your key strokes.
Click on the DOM and notice that your keystrokes are being logged properly.
Use Case: Form opens an iframe and submits, then removes itself from the DOM. I want to be able to detect keyboard events after the form is submitted without the user needing to use their mouse.
Question: I thought the top most DOM element was "window" and if this is not capturing the keyboard events, what is? There are no other DOMs currently present (i.e. iframes) as far as I know. I tested this is both firefox and chrome. Any explanation as to what is happening and why what I am trying to do is not possible or a way to capture the events would be greatly appreciated.
(My current solution is to use a MutationObserver to watch for the iframe to disappear and force focus back on the window. I also know I could use a setInterval to continually check for the iframe. Both solution feel like I am doing extra work).
after closing the iframe, focus the window using $(window).focus(); if you must
in the sample you'd do it like
$iframe.load(function(){
window.setTimeout(function(){
console.log("deleting");
$("#deleteMe iframe").remove();
$(window).focus(); // <======
}, 5000);
});
I created a simple JavaScript function to display my pop-up window once it loads. But it keeps on being blocked by Firefox and Google Chrome and I have to somehow enable it on the Firefox and Chrome to display the pop-up.
Are there any alternatives for this?
I have a player on the pop-up window so I have to use a pop-up to let the player play automatically. The problem is that if I put it on the page itself, once the user clicks another page the entire page reloads and the player automatically stops for a few seconds until the whole page reloads and I have to prevent this from happening.
The general rule is that popup blockers will engage if window.open or similar is invoked from javascript that is not invoked by direct user action. That is, you can call window.open in response to a button click without getting hit by the popup blocker, but if you put the same code in a timer event it will be blocked. Depth of call chain is also a factor - some older browsers only look at the immediate caller, newer browsers can backtrack a little to see if the caller's caller was a mouse click etc. Keep it as shallow as you can to avoid the popup blockers.
Please take a look at dthorpe's answer here. It covers your question.
You could try putting the player on the original page, and using something like History.js to control page changes (you could have the main page body in one wrapper div that changes, and leave the player outside of it).
Otherwise, you could try (assuming you meant a HTML5 <video> or <audio> player) downloading the data to localStorage/cookie/[other persistent storage mechanism] and have it seek everytime you change a page.
It will be hard to stop browsers from blocking your pop up window, because any way to do so is inherently exploitable; however, if you call the function to open another window from an onclick event, you may be able to circumvent some popup blockers. Also, some popup blockers allow popups when using the https protocol, although not many have this feature, and https can be hard to implement for the average website, if you don't have physical access to the server.
One other option is to open the other page in another tab (like this w3c example; you can 'click' the link with javascript).
You might also want to look at this post, as it is somewhat similar.
I only just discovered you asked this question.
Here's the answer in full.
Basically, you can simply create the popup immediately as the user event is fired, then fill it with content (your player, for instance) as you have it available.
I am writing a widget which gets embedded on other pages (on other domains) via an iframe. A click anywhere on the widget/iframe should bring up a dialog. The dialog does not fit in the dimensions of the iframe.
I cannot trigger the dialog from inside the widget/iframe since it will get clipped by the iframe dimensions.
A user of the widget also includes a JS from my site. But I cannot listen to onclick events on the iframe (on the host page) since they aren't any onclick events on an iframe.
What's a good, secure way of resolving this which will reliably work on all modern browsers?
Have a look at these PostMessage plugins 1 / 2 which allow you to communicate i.e. pass messages between an iFrame on another domain and the parent page.
This means you can listen for the click on the iFrame, then send a message to the parent. When the parent receives that message, it can then show a dialog