I have a script that closes an iframe after a click it.
I need that when you click on the link inside the iframe has delay 15 seconds to load a page within the iframe and after 15 seconds the iframe automatically closes.
$(window).on('blur',function(e) {
if($(this).data('mouseIn') != 'yes')return;
$('iframe').filter(function(){
return $(this).data('mouseIn') == 'yes';
}).trigger('iframeclick');
});
$(window).mouseenter(function(){
$(this).data('mouseIn', 'yes');
}).mouseleave(function(){
$(this).data('mouseIn', 'no');
});
$('iframe').mouseenter(function(){
$(this).data('mouseIn', 'yes');
$(window).data('mouseIn', 'yes');
}).mouseleave(function(){
$(this).data('mouseIn', null);
});
$('iframe').on('iframeclick', function(){
$(this).hide()
});
$('<input type="text" style="position:absolute;opacity:0;height:0px;width:0px;"/>').appendTo(document.body).blur(function(){
$(window).trigger('blur');
}).focus();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<iframe style="width:400px;
height:250px;" src="//example.com"></iframe>
If you want to stick to Jquery you can use .delay()
http://api.jquery.com/delay/
To wait 15 seconds before the iframe close, you should do this :
$('iframe').on('iframeclick', function(){
$(this).delay(15000).hide();
}
In a simple way, you put a delay of 15s before the "hide" action
You are looking for the setTimeout() method. You can find how to use it here: http://www.w3schools.com/jsref/met_win_settimeout.asp.
In your case would be something like (this can be optimized, take out global var etc.):
globalVar = null;
function closeIframe() {
globalVar.hide();
}
$('iframe').on('iframeclick', function(){
globalVar = $(this);
setTimeout("closeIframe()", 15000);
});
Use good old setTimeout:
var timeoutValue = 15000; /*ms*/
setTimeout(function(){...}, timeoutValue);
which in you case could look like:
var close = function(element){element.hide();};
$('iframe').on('iframeclick', function(){
var timeoutValue = 15000;
var context = $(this);
setTimeout(function(){close(context)}, timeoutValue);
});
Binding event listeners to elements inside the iframe will only work if both the parent site and the iframe are on the same domain. If the contents of the iframe is on a different domain, you won't be able to perform this as it is classed as "click-jacking", which is a big security threat. See http://en.wikipedia.org/wiki/Same-origin_policy
If the iframe is on the same domain then you can add the event listener inside the iframe and then call the parent to notify the event.
You can also grab the contents and find the element you want to bind the event handler on.
$("iframe#name").contents().find(".link").on("click", function() {
$("iframe#name").delay(15000).hide();
});
Related:
How to add click event to a iframe with JQuery
Click-event on iframe?
Bind to events inside dynamically created iframe
Ways to circumvent the same-origin policy
Detect click inside iframe (same domain/sub domain) in Chrome using jQuery
I used sleep () function and solved my problem!
Related
I have an iframe on a page, coming from a 3rd party (an ad). I'd like to fire a click event when that iframe is clicked in (to record some in-house stats). Something like:
$('#iframe_id').click(function() {
//run function that records clicks
});
..based on HTML of:
<iframe id="iframe_id" src="http://something.com"></iframe>
I can't seem to get any variation of this to work. Thoughts?
There's no 'onclick' event for an iframe, but you can try to catch the click event of the document in the iframe:
document.getElementById("iframe_id").contentWindow.document.body.onclick =
function() {
alert("iframe clicked");
}
EDIT
Though this doesn't solve your cross site problem, FYI jQuery has been updated to play well with iFrames:
$('#iframe_id').on('click', function(event) { });
Update 1/2015
The link to the iframe explanation has been removed as it's no longer available.
Note
The code above will not work if the iframe is from different domain than the host page. You can still try to use hacks mentioned in comments.
I was trying to find a better answer that was more standalone, so I started to think about how JQuery does events and custom events. Since click (from JQuery) is just any event, I thought that all I had to do was trigger the event given that the iframe's content has been clicked on. Thus, this was my solution
$(document).ready(function () {
$("iframe").each(function () {
//Using closures to capture each one
var iframe = $(this);
iframe.on("load", function () { //Make sure it is fully loaded
iframe.contents().click(function (event) {
iframe.trigger("click");
});
});
iframe.click(function () {
//Handle what you need it to do
});
});
});
Try using this : iframeTracker jQuery Plugin, like that :
jQuery(document).ready(function($){
$('.iframe_wrap iframe').iframeTracker({
blurCallback: function(){
// Do something when iframe is clicked (like firing an XHR request)
}
});
});
It works only if the frame contains page from the same domain (does
not violate same-origin policy)
See this:
var iframe = $('#your_iframe').contents();
iframe.find('your_clicable_item').click(function(event){
console.log('work fine');
});
You could simulate a focus/click event by having something like the following.
(adapted from $(window).blur event affecting Iframe)
$(window).blur(function () {
// check focus
if ($('iframe').is(':focus')) {
console.log("iframe focused");
$(document.activeElement).trigger("focus");// Could trigger click event instead
}
else {
console.log("iframe unfocused");
}
});
//Test
$('#iframe_id').on('focus', function(e){
console.log(e);
console.log("hello im focused");
})
None of the suggested answers worked for me. I solved a similar case the following way:
<iframe id="iframe_id" src="http://something.com" allowtrancparency="yes" frameborder="o"></iframe>
The css (of course exact positioning should change according to the app requirements):
#iframe-wrapper, iframe#iframe_id {
width: 162px;
border: none;
height: 21px;
position: absolute;
top: 3px;
left: 398px;
}
#alerts-wrapper {
z-index: 1000;
}
Of course now you can catch any event on the iframe-wrapper.
You can use this code to bind click an element which is in iframe.
jQuery('.class_in_iframe',jQuery('[id="id_of_iframe"]')[0].contentWindow.document.body).on('click',function(){
console.log("triggered !!")
});
This will allow you to target a specfic element in the iframe such as button or text fields or practically anything as on method allows you to put selector as an argument
$(window).load(function(){
$("#ifameid").contents().on('click' , 'form input' , function(){
console.log(this);
});
});
Maybe somewhat old but this could probably be useful for people trying to deal with same-domain-policy.
let isOverIframe = null;
$('iframe').hover(function() {
isOverIframe = true;
}, function() {
isOverIframe = false;
});
$(window).on('blur', function() {
if(!isOverIframe)
return;
// ...
});
Based on https://gist.github.com/jaydson/1780598
You may run into some timing issues depending on when you bind the click event but it will bind the event to the correct window/document. You would probably get better results actually binding to the iframe window though. You could do that like this:
var iframeWin = $('iframe')[0].contentWindow;
iframeWin.name = 'iframe';
$(iframeWin).bind('click', function(event) {
//Do something
alert( this.name + ' is now loaded' );
});
This may be interesting for ppl using Primefaces (which uses CLEditor):
document.getElementById('form:somecontainer:editor')
.getElementsByTagName('iframe')[0].contentWindow
.document.onclick = function(){//do something}
I basically just took the answer from Travelling Tech Guy and changed the selection a bit .. ;)
Solution that work for me :
var editorInstance = CKEDITOR.instances[this.editorId];
editorInstance.on('focus', function(e) {
console.log("tadaaa");
});
You can solve it very easily, just wrap that iframe in wrapper, and track clicks on it.
Like this:
<div id="iframe_id_wrapper">
<iframe id="iframe_id" src="http://something.com"></iframe>
</div>
And disable pointer events on iframe itself.
#iframe_id { pointer-events: none; }
After this changes your code will work like expected.
$('#iframe_id_wrapper').click(function() {
//run function that records clicks
});
I have a iFrame on my page thats display style is none. I have a javascript function to set the source and then set the display to block. The problem is that the iframe shows up before the content of it is loaded and thus I get a flickering effect. It goes white first and then displays the content. So I need to set the source, and when done loading all content of its source, only set its display style.
CSS & Javascript
.ShowMe{display:block;}
function(url)
{
document.getElementById('myIFrame').src = url;
document.getElementById('myIFrame').className = ShowMe;
}
It's simple as that:
<iframe onload="this.style.opacity=1;" style="opacity:0;border:none;
I would suggest you try the following:
<script type="javascript">
var iframe = document.createElement("myIFrame");
iframe.src = url;
if (navigator.userAgent.indexOf("MSIE") > -1 && !window.opera){
iframe.onreadystatechange = function(){
if (iframe.readyState == "complete"){
//not sure if your code works but it is below for reference
document.getElementById('myIFrame').class = ShowMe;
//or this which will work
//document.getElementById("myIFrame").className = "ShowMe";
}
};
}
else
{
iframe.onload = function(){
//not sure if your code works but it is below for reference
document.getElementById('myIFrame').class = ShowMe;
//or this which will work
//document.getElementById("myIFrame").className = "ShowMe";
};
}
</script>
Based on the code found here.
You could do this within the iframe:
window.onload = function () {
window.frameElement.className = 'ShowMe'; // 'ShowMe' or what ever you have in ShowMe variable.
}
Since you've tagged your question with [jquery], I assume you have executed the code within $(document).ready(). It is fired when the DOM is ready, i.e. it uses native DOMContentLoaded event (if available). window.onload is fired, when all resources on the page are ready.
The site I'm working on has a Live Chat plugin on an iframe. I'm trying to change an image if there are no agents available. My code works on the console, but nothing on the site.
var LiveChatStatus = $("iframe").contents().find(".agentStatus").html();
if (LiveChatStatus =="Offline"){
$('#liveChat').html('<img src="%%GLOBAL_ShopPath%%/product_images/theme_images/liveoffline.png">');
}
I tried this:
$('iframe').ready(function(){
var LiveChatStatus = $("iframe").contents().find(".agentStatus").html();
if (LiveChatStatus =="Offline"){
$('#liveChat').html('<img src="%%GLOBAL_ShopPath%%/product_images/theme_images/liveoffline.png">');
}
});
And this:
$(document).ready(function(){
var LiveChatStatus = $("iframe").contents().find(".agentStatus").html();
if (LiveChatStatus =="Offline"){
$('#liveChat').html('<img src="%%GLOBAL_ShopPath%%/product_images/theme_images/liveoffline.png">');
}
});
But neither worked
The best solution is to define a function in your parent such as function iframeLoaded(){...} and then in the iframe use:
$(function(){
parent.iframeLoaded();
})
this works cross-browser.
If you cannot change the code within the iframe, your best solution will be to attach the load event to the iframe..
$(function(){
$('iframe').on('load', function(){some code here...}); //attach the load event listener before adding the src of the iframe to prevent from the handler to miss the event..
$('iframe').attr('src','http://www.iframe-source.com/'); //add iframe src
});
Another way to bind to the load event of an iframe is to attach a load listener to the iframe before adding a src tag to the iframe.
Here's a simple example. This will also work with iframes that you don't control.
http://jsfiddle.net/V42ts/
// First add the listener.
$("#frame").load(function(){
alert("loaded!");
});
// Then add the src
$("#frame").attr({
src:"https://apple.com"
})
Found this from Elijah Manor's website which works very well
function iFrameLoaded(id, src) {
var deferred = $.Deferred(),
iframe = $("<iframe class='hiddenFrame'></iframe>").attr({
"id": id,
"src": src
});
iframe.load(deferred.resolve);
iframe.appendTo("body");
deferred.done(function() {
console.log("iframe loaded: " + id);
});
return deferred.promise();
}
$.when(iFrameLoaded("jQuery", "http://jquery.com"), iFrameLoaded("appendTo", "http://appendto.com")).then(function() {
console.log("Both iframes loaded");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
is it possible for me to make a jquery function run in an iframe using hash links?
perhaps something like this:
Parent code:
run function in iframe
<iframe src="pageName.html" name="iframe"></iframe>
Iframe code:
$(document).ready(function(){
$('body').the parent link is clicked, changing the url to pageName.html#runFunction (function(){
//blah blah blah//
});
});
thanks
Yes you can using the hashchange event. As long as you don't mind not supporting IE7 http://caniuse.com/hashchange
Alternatively, there is also a plugin that will backfill for you: http://benalman.com/projects/jquery-hashchange-plugin/
On the parent page simply change the URL of the iframe to a new hash.
$("iframe").prop("src", "http://google.com/#newhash");
Then in the docready of the iframe page:
$(window).bind("hashchange", function() {
alert(window.location.hash);
});
I am not sure exactly what you are trying here... but you can try this:
Where 'myIFrameFunction' is a function inside of 'pageName.html'...
Parent HTML:
click me for win
<iframe src="pageName.html"></iframe>
Iframe Javascript (as long as the function to be called is declared globally[direct in a script tag or js file]):
function testHash() {
var hash = window.location.hash.split('#')[1];
if ( typeof window[hash] != 'undefined' ) {
window[hash]();
}
}
var myTimer = setInterval(testHash, 100);
function myIFrameFunction() {
alert('It Works!');
}
I'm fairly new to Javascript in general, and I cobbled together a small script from things found mostly on this site to try to get a small iframe to cycle through a bunch of links, which it does brilliantly. However, I also want it to stop cycling when the user clicks on the iframe or any of its contents.
Here is the code I have so far. There is only one iframe on the HTML page.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8">
<!--
var sites = [
"side/html5.html",
"side/silverlight.html",
"side/wordpress.html",
"side/mysql.html",
"side/php.html",
"side/css3.html"
];
var currentSite = sites.length;
var timerId;
var iframeDoc = $("iframe").contents().get(0);
$(document).ready(function ()
{
var $iframe = $("iframe").attr("src","side/html5.html");
timerId = setInterval(function()
{
(currentSite == 0) ? currentSite = sites.length - 1 : currentSite = currentSite -1;
$iframe.attr("src",sites[currentSite]);
}, 4000);
$(iframeDoc).bind('click', function()
{
clearInterval(timerId);
});
});
//-->
</script>
</head>
<body>
<sidebar>
<iframe name="sideframe" src="side/html5.html"></iframe>
</sidebar> ..etc..
Please help, I am trying to learn Javascript as fast as I can but as far as I can see, it should work, but it really doesn't.
Thanks for any help you can give me, it's really appreciated.
EDIT:
Okay, I've got a new script now, mostly based off of Elias' work, but it doesn't work either. I've pinned it down in Firebug and it's saying that the timerCallback.currentSite value IS updating properly, though I can't find the $iframe's src value to check for it explicitly. As far as I can tell, it is updating the variables properly, it's just not updating the iframe properly. Am I calling/setting the iframe correctly in this code? Also, is the linked in jquery library sufficient for my purposes? I'm a little lost of all these libraries to link to...
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript" charset="utf-8">
<!--
var sites =
[
"side/html5.html",
"side/silverlight.html",
"side/wordpress.html",
"side/mysql.html",
"side/php.html",
"side/css3.html"
];
var $iframe = $("iframe").attr("src","side/html5.html");
function timerCallback()
{
timerCallback.currentSite = (timerCallback.currentSite ? timerCallback.currentSite : sites.length) -1;
$iframe.attr("src",sites[timerCallback.currentSite]);
$($('iframe').contents().get('body')).ready(function()
{
$(this).unbind('click').bind('click',function()
{
var theWindow = (window.location !== window.parent.location ? window.parent : window);
theWindow.clearInterval(theWindow.timerId);
});
});
}
var timerId = setInterval(timerCallback, 4000);
//-->
</script>
If I were you, I'd play it safe. Since you say you're fairly new to JS, it might prove very informative.
function timerCallback()
{
timerCallback.currentSite = (timerCallback.currentSite ? timerCallback.currentSite : sites.length) -1;
$iframe.attr("src",sites[timerCallback.currentSite]);
}
var timerId = setInterval(timerCallback, 4000);
$($('iframe').contents().get('body')).unbind('click').bind('click', function()
{
var theWindow = (window.location !== window.parent.location ? window.parent : window);
theWindow.clearInterval(theWindow.timerId);
});
Now I must admit that this code is not tested, at all. Though I think it provides a couple of things to get you on your way:
1) the interval is set using a callback function, because it's just better for tons of reasons
1b) in that Callback, I took advantage of the fact that functions are objects, and created a static var, that is set to either the length of your sites array (when undefined or 0), in both cases 1 is substracted
2) jQuery's ,get() method returns a DOM element, not a jquery object, that's why I wrapped it in $(), a new jQ obj, giving you the methods you need.
3) since you're manipulating the dom inside the iFrame, it's best to unbind events you want to bind
4) inside the iFrame, you don't have direct access to the parent window, where your interval is.
You might want to read up on how to deal with iFrames, because they can be a bit of a faff from time to time
EDIT:
David Diez is right, easiest way around this is to incorporate the binding in the timeout function:
function timerCallback()
{
timerCallback.currentSide = ...//uncanged
//add this:
$($('iframe').contents().get('body')).ready(function()
{
$(this).unbind('click').bind('click',function()
{
//this needn't change
});
});
}
In theory, this should bind the click event to the body after it has been loaded
Edit2
I've been messing around a bit, you could keep your code, as is. just add a function:
function unsetInterval()
{
window.clearInterval(window.timerId);
}
and add this to your setInterval function:
$('#idOfIframe').load(function()
{
var parentWindow = window.parent;
$('body').on('click',function()
{
parentWindow.clearInterval();
});
});
this will get triggered as soon as the iFrame content is loaded, and bind the click event and unset the timer, like you wanted to
I think your code is not working because of this
var iframeDoc = $("iframe").contents().get(0);
This could be getting the header of the iFrame because you are saving the iframeDoc value to the first child of the iframe, the head tag, actually if you have more than 1 iframe in your window iframeDoc would be undefined because $("iframe") gets all the iframes of your document.
BTW your currentSite value condition is wrong, you asign the same value for both conditions
Now I give you an example:
<iframe id="myFrame" src="http://www.google.com/"></iframe>
and the script:
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
var sites = [
"site1",
"site2"
];
var myFrame = document.getElementsByTagName('iframe')[0];
var currentSite = myFrame.getAttribute('src');
var timerId;
var myFrameDoc = window.frames[0].document;
$(document).ready(function()
{
myFrame.setAttribute('src', 'side/html5.html');
timerId = setInterval(function()
{
//WRONGG
(currentSite == 0) ? currentSite = sites.length - 1 : currentSite = currentSite -1;
myFrame.setAttribute('src', sites[currentSite]);
$(myFrame).off("click").on("click", clearInterval(timerId));
}, 4000);
//Won't work because you are trying to get events from an inside of a iframe
//$(myFrameDoc).on("click", clearInterval(timerId));
//This may work
$(myFrameDoc).off("click").on("click", clearInterval(timerId));
});
</script>
When you try to track the events of an iframe you have to be carefull because an iframe contains a totally different document for javascript purprouses so basically you have to get inside the new document, unbind the events you need to use, and bind them again against your functionality, as #Elias points out. but be aware that you are changing constantly the src of your iframe, so if yu really need to do that you will have to separate the code that unbinds and binds again your clearInterval, and for that matter maybe $.on() could work for you.
EDIT: Calling to the iframe should work this way IF the src of the iframe is inside the same domain, with the same port and with the same protocol:
var myFrameDoc = window.frames[0].document;
I Added a new variable because we want to bind and unbind the click event to the iframe's document, not to the iframe, we use for that the window.frames collection property, but modern browsers throw an exception and denies acces if you try to access to a frame and you are not on the same domain with using the same port and the same protocol...
Additionaly the use of $.on() and $.off() instead of $.bind and $.unbind() is because the first ones are the new ones and despite we are not using it here, they are capable of watch constantly the DOM for new elements to bind if added; that could be useful to this case if this code still doesn't work. If that is the case you can still change this:
var myFrameDoc = window.frames[0].window;
and this:
$(myFrameDoc).off("click", "document").on("click", "document", clearInterval(timerId));
This will re-bind the event handler to new documents additions. Not tested but could work.