jQuery/JS Resize of iframe not working - javascript

I try to resize an iframe with jQuery and JS. First I get the iframe out of a list of iframes and resize it when the iframe-content is ready.
NOTE: The two-steps resize is necessary because otherwise after the
content of the iframe-page is a huge space.
Problem: In the while-loop I check if the content of the iframe is ready, when not I set a timeout of 1 second. But jQuery don’t check if the content ready it always goes inside the if and try to resize the iframe but fails because jQuery cannot get the size of a NULL element.
Has someone of you a solution for my problem?
My Code:
$(document).ready(function () {
var iframes = $(".my-iframe");
$.each(iframes, function () {
resizeIframe(this);
});
});
function resizeIframe(iframe) {
$(iframe).width("100%");
var iframeIsReady = false;
do
{
if ($(iframe).ready)
{
var iframeHeight = iframe.contentDocument.body.scrollHeight;
$(iframe).height(iframeHeight);
var iframeContentHeight = $(iframe).children("#DivInPage").height();
$(iframe).height(iframeContentHeight);
iframeIsReady = true;
}
else
{
setTimeout(resizeIframe(iframe), 1000);
}
}while(!iframeIsReady);
}
Edit:
Check out my solution

Hi there is small change in your code please check following.
$(document).ready(function () {
var iframes = $(".my-iframe")[0]; // $(".my-iframe"); /Edited
$.each(iframes, function () {
resizeIframe(this);
});
});
function resizeIframe(iframe) {
$(iframe).width("100%");
var iframeIsReady = false;
do
{
if ($(iframe.contentDocument).ready) // added 'iframe.contentDocument' instead of iframe
{
var iframeHeight = iframe.contentDocument.body.scrollHeight;
$(iframe).height(iframeHeight);
var iframeContentHeight = $(iframe).children("#DivInPage").height();
$(iframe).height(iframeContentHeight);
iframeIsReady = true;
}
else
{
setTimeout(resizeIframe(iframe), 1000);
}
}while(!iframeIsReady);
}
try this.
I checked code again found that $(".my-iframe") returns array of element object.
We need object here not array.
So i hard coded 0th index. you can use id instead of this.

Solution of my problem is:
$(document).ready(function () {
var iframes = $(".my-iframe");
$.each(iframes, function () {
resizeIframe(this);
});
});
function resizeIframe(iframe) {
$(iframe).width("100%");
setInterval(function () {
//Check if the Content inside the iframe is ready
if ($(iframe.contentDocument.body).ready) {
var iframeHeight = iframe.contentDocument.body.scrollHeight;
$(iframe).height(iframeHeight);
var iframeContentHeight = $(iframe).children("#DivInPage").height();
$(iframe).height(iframeContentHeight);
//Close the Function
return;
}
}, 1000);
}

Related

jQuery - Why does my function break if called on document.ready?

I'm doing some HTML prototyping to explore some UX stuff. Whilst trying to work out why a Javascript function (which uses a lot of jQuery) wasn't working I broke it out into a JS Fiddle. It seems that when the function is called on document.ready it won't work and can't be executed with a click event. However, if it isn't called at document.ready then it will work! I'm probably missing something obvious...
Working: http://jsfiddle.net/NWmB5/
$(document).ready(function() {
$('#targetFirstDiv').click(function() {
setTimelinePosition($('#anotherDiv'));
});
$('#targetSecondDiv').click(function() {
setTimelinePosition($('#testDiv'));
});
});
var toDoCategories = [$("#testDiv"),$("#anotherDiv")];
/* Show current position on timeline */
function setTimelinePosition($position) {
var $theTimelineTrigger = $('span.timelineTrigger');
toDoCategories.forEach(function(currentCategory) {
var $deselectTimelinePositionElement = $(currentCategory, $theTimelineTrigger);
$($deselectTimelinePositionElement).removeClass('currentPosition');
});
var $selectTimelinePositionElement = ($($position,$theTimelineTrigger));
$($selectTimelinePositionElement).addClass('currentPosition');
}
Not Working: http://jsfiddle.net/NWmB5/5/
$(document).ready(function() {
setTimelinePosition($('#thirdDiv'));
$('#targetFirstDiv').click(function() {
setTimelinePosition($('#anotherDiv'));
});
$('#targetSecondDiv').click(function() {
setTimelinePosition($('#testDiv'));
});
});
var toDoCategories = [$("#testDiv"),$("#anotherDiv"),$("thirdDiv")];
/* Show current position on timeline */
function setTimelinePosition($position) {
var $theTimelineTrigger = $('span.timelineTrigger');
toDoCategories.forEach(function(currentCategory) {
var $deselectTimelinePositionElement = $(currentCategory, $theTimelineTrigger);
$($deselectTimelinePositionElement).removeClass('currentPosition');
});
var $selectTimelinePositionElement = ($($position,$theTimelineTrigger));
$($selectTimelinePositionElement).addClass('currentPosition');
}
You trying to get $("#testDiv"),$("#anotherDiv"),$("thirdDiv") before DOM ready event fired that's where the exact problem.Try after DOM ready fired
var toDoCategories = [$("#testDiv"),$("#anotherDiv"),$("thirdDiv")];
So get $("#testDiv"),$("#anotherDiv"),$("thirdDiv") after DOM ready event dispatched.
var toDoCategories; //NOTE HERE
$(document).ready(function() {
toDoCategories = [$("#testDiv"),$("#anotherDiv"),$("thirdDiv")]; //NOTE HERE
setTimelinePosition($('#thirdDiv'));
$('#targetFirstDiv').click(function() {
setTimelinePosition($('#anotherDiv'));
});
$('#targetSecondDiv').click(function() {
setTimelinePosition($('#testDiv'));
});
});
/* Show current position on timeline */
function setTimelinePosition($position) {
var $theTimelineTrigger = $('span.timelineTrigger');
toDoCategories.forEach(function(currentCategory) {
var $deselectTimelinePositionElement = $(currentCategory, $theTimelineTrigger);
$($deselectTimelinePositionElement).removeClass('currentPosition');
});
var $selectTimelinePositionElement = ($($position,$theTimelineTrigger));
$($selectTimelinePositionElement).addClass('currentPosition');
}

Jquery plugin stops working correctly after window.resize, but works well after full page refresh

I'm implementing a jquery carousel into my page. Because I have used percentage units rather than fixed units, I need to redraw the carousel after window resize.
My problem is that the carousel stops to work correctly and its function call does not behave normally and renders the carousel oddly after resizing using the following code:
jQuery(document).ready(function ($) {
FnUpdateCarousel();
}); // end ready
var lightbox_resize = false;
$(window).resize(function() {
if (lightbox_resize)
clearTimeout(lightbox_resize);
lightbox_resize = setTimeout(function() {
FnUpdateCarousel();
}, 100);
});
function FnUpdateCarousel() {
var widthof =
Math.round(parseInt(jQuery('#services-example-1').css('width'))-(45));
jQuery('#services-example-1').services(
{
width:widthof,
height:290,
slideAmount:6,
slideSpacing:30,
touchenabled:"on",
mouseWheel:"on",
hoverAlpha:"off",
slideshow:3000,
hovereffect:"off"
});
};
Please guide me on how can I make it behave normally.
Here is the solution I reached:
<script type="text/javascript">
var initialContent = jQuery('#services-example-1').html();
jQuery(document).ready(function ($) {
FnUpdateCarousel();
}); // end ready
var lightbox_resize = false;
$(window).resize(function() {
if (lightbox_resize)
clearTimeout(lightbox_resize);
lightbox_resize = setTimeout(function() {
jQuery('#services-example-1').empty();
jQuery('#services-example-1').html(initialContent);
FnUpdateCarousel();
}, 200);
});
function FnUpdateCarousel() {
var widthof =
Math.round(parseInt(jQuery('#services-example-1').css('width'))-(45));
jQuery('#services-example-1').services(
{
width:widthof,
height:290,
slideAmount:6,
slideSpacing:30,
touchenabled:"on",
mouseWheel:"on",
hoverAlpha:"off",
slideshow:3000,
hovereffect:"off"
});
};
</script>

How to detect if some text box is changed via external script?

I have some jQuery plugin that changes some elements, i need some event or jQuery plugin that trigger an event when some text input value changed.
I've downloaded jquery.textchange plugin, it is a good plugin but doesn't detect changes via external source.
#MSS -- Alright, this is a kludge but it works:
When I call boxWatcher() I set the value to 3,000 but you'd need to do it much more often, like maybe 100 or 300.
http://jsfiddle.net/N9zBA/8/
var theOldContent = $('#theID').val().trim();
var theNewContent = "";
function boxWatcher(milSecondsBetweenChecks) {
var theLoop = setInterval(function() {
theNewContent = $('#theID').val().trim();
if (theOldContent == theNewContent) {
return; //no change
}
clearInterval(theLoop);//stop looping
handleContentChange();
}, milSecondsBetweenChecks);
};
function handleContentChange() {
alert('content has changed');
//restart boxWatcher
theOldContent = theNewContent;//reset theOldContent
boxWatcher(3000);//3000 is about 3 seconds
}
function buttonClick() {
$('#theID').value = 'asd;lfikjasd;fkj';
}
$(document).ready(function() {
boxWatcher(3000);
})
try to set the old value into a global variable then fire onkeypress event on your text input and compare between old and new values of it. some thing like that
var oldvlaue = $('#myInput').val();
$('#myInput').keyup(function(){
if(oldvlaue!=$('#myInput').val().trim())
{
alert('text has been changed');
}
});
you test this example here
Edit
try to add an EventListner to your text input, I don't know more about it but you can check this Post it may help
Thanks to #Darin because of his/her solution I've marked as the answer, but i have made some small jQuery plugin to achieve the same work named 'txtChgMon'.
(function ($) {
$.fn.txtChgMon = function (func) {
var res = this.each(function () {
txts[0] = { t: this, f: func, oldT: $(this).val(), newT: '' };
});
if (!watchStarted) {
boxWatcher(200);
}
return res;
};
})(jQuery);
var txts = [];
var watchStarted = false;
function boxWatcher(milSecondsBetweenChecks) {
watchStarted = true;
var theLoop = setInterval(function () {
for (var i = 0; i < txts.length; i++) {
txts[i].newT = $(txts[i].t).val();
if (txts[i].newT == txts[i].oldT) {
return; //no change
}
clearInterval(theLoop); //stop looping
txts[i].f(txts[i], txts[i].oldT, txts[i].newT);
txts[i].oldT = $(txts[i].t).val();
boxWatcher(milSecondsBetweenChecks);
return;
}
}, milSecondsBetweenChecks);
}

Javascript "while hovered" loop

Can anybody help me on this one...I have a button which when is hovered, triggers an action. But I'd like it to repeat it for as long as the button is hovered.
I'd appreciate any solution, be it in jquery or pure javascript - here is how my code looks at this moment (in jquery):
var scrollingposition = 0;
$('#button').hover(function(){
++scrollingposition;
$('#object').css("right", scrollingposition);
});
Now how can i put this into some kind of while loop, so that #object is moving px by px for as #button is hovered, not just when the mouse enters it?
OK... another stab at the answer:
$('myselector').each(function () {
var hovered = false;
var loop = window.setInterval(function () {
if (hovered) {
// ...
}
}, 250);
$(this).hover(
function () {
hovered = true;
},
function () {
hovered = false;
}
);
});
The 250 means the task repeats every quarter of a second. You can decrease this number to make it faster or increase it to make it slower.
Nathan's answer is a good start, but you should also use window.clearInterval when the mouse leaves the element (mouseleave event) to cancel the repeated action which was set up using setInterval(), because this way the "loop" is running only when the mouse pointer enters the element (mouseover event).
Here is a sample code:
function doSomethingRepeatedly(){
// do this repeatedly when hovering the element
}
var intervalId;
$(document).ready(function () {
$('#myelement').hover(function () {
var intervalDelay = 10;
// call doSomethingRepeatedly() function repeatedly with 10ms delay between the function calls
intervalId = setInterval(doSomethingRepeatedly, intervalDelay);
}, function () {
// cancel calling doSomethingRepeatedly() function repeatedly
clearInterval(intervalId);
});
});
I created a sample code on jsFiddle which demonstrates how to scroll the background-image of an element left-to-right and then backwards on hover with the code shown above:
http://jsfiddle.net/Sk8erPeter/HLT3J/15/
If its an animation you can "stop" an animation half way through. So it looks like you're moving something to the left so you could do:
var maxScroll = 9999;
$('#button').hover(
function(){ $('#object').animate({ "right":maxScroll+"px" }, 10000); },
function(){ $('#object').stop(); } );
var buttonHovered = false;
$('#button').hover(function () {
buttonHovered = true;
while (buttonHovered) {
...
}
},
function () {
buttonHovered = false;
});
If you want to do this for multiple objects, it might be better to make it a bit more object oriented than a global variable though.
Edit:
Think the best way of dealing with multiple objects is to put it in an .each() block:
$('myselector').each(function () {
var hovered = false;
$(this).hover(function () {
hovered = true;
while (hovered) {
...
}
},
function () {
hovered = false;
});
});
Edit2:
Or you could do it by adding a class:
$('selector').hover(function () {
$(this).addClass('hovered');
while ($(this).hasClass('hovered')) {
...
}
}, function () {
$(this).removeClass('hovered');
});
var scrollingposition = 0;
$('#button').hover(function(){
var $this = $(this);
var $obj = $("#object");
while ( $this.is(":hover") ) {
scrollingposition += 1;
$obj.css("right", scrollingposition);
}
});

setInterval with other jQuery events - Too many recursions

I'm trying to build a Javascript listener for a small page that uses AJAX to load content based on the anchor in the URL. Looking online, I found and modified a script that uses setInterval() to do this and so far it works fine. However, I have other jQuery elements in the $(document).ready() for special effects for the menus and content. If I use setInterval() no other jQuery effects work. I finagled a way to get it work by including the jQuery effects in the loop for setInterval() like so:
$(document).ready(function() {
var pageScripts = function() {
pageEffects();
pageURL();
}
window.setInterval(pageScripts, 500);
});
var currentAnchor = null;
function pageEffects() {
// Popup Menus
$(".bannerMenu").hover(function() {
$(this).find("ul.bannerSubmenu").slideDown(300).show;
}, function() {
$(this).find("ul.bannerSubmenu").slideUp(400);
});
$(".panel").hover(function() {
$(this).find(".panelContent").fadeIn(200);
}, function() {
$(this).find(".panelContent").fadeOut(300);
});
// REL Links Control
$("a[rel='_blank']").click(function() {
this.target = "_blank";
});
$("a[rel='share']").click(function(event) {
var share_url = $(this).attr("href");
window.open(share_url, "Share", "width=768, height=450");
event.preventDefault();
});
}
function pageURL() {
if (currentAnchor != document.location.hash) {
currentAnchor = document.location.hash;
if (!currentAnchor) {
query = "section=home";
} else {
var splits = currentAnchor.substring(1).split("&");
var section = splits[0];
delete splits[0];
var params = splits.join("&");
var query = "section=" + section + params;
}
$.get("loader.php", query, function(data) {
$("#load").fadeIn("fast");
$("#content").fadeOut(100).html(data).fadeIn(500);
$("#load").fadeOut("fast");
});
}
}
This works fine for a while but after a few minutes of the page being loaded, it drags to a near stop in IE and Firefox. I checked the FF Error Console and it comes back with an error "Too many Recursions." Chrome seems to not care and the page continues to run more or less normally despite the amount of time it's been open.
It would seem to me that the pageEffects() call is causing the issue with the recursion, however, any attempts to move it out of the loop breaks them and they cease to work as soon as setInterval makes it first loop.
Any help on this would be greatly appreciated!
I am guessing that the pageEffects need added to the pageURL content.
At the very least this should be more efficient and prevent duplicate handlers
$(document).ready(function() {
pageEffects($('body'));
(function(){
pageURL();
window.setTimeout(arguments.callee, 500);
})();
});
var currentAnchor = null;
function pageEffects(parent) {
// Popup Menus
parent.find(".bannerMenu").each(function() {
$(this).unbind('mouseenter mouseleave');
var proxy = {
subMenu: $(this).find("ul.bannerSubmenu"),
handlerIn: function() {
this.subMenu.slideDown(300).show();
},
handlerOut: function() {
this.subMenu.slideUp(400).hide();
}
};
$(this).hover(proxy.handlerIn, proxy.handlerOut);
});
parent.find(".panel").each(function() {
$(this).unbind('mouseenter mouseleave');
var proxy = {
content: panel.find(".panelContent"),
handlerIn: function() {
this.content.fadeIn(200).show();
},
handlerOut: function() {
this.content.slideUp(400).hide();
}
};
$(this).hover(proxy.handlerIn, proxy.handlerOut);
});
// REL Links Control
parent.find("a[rel='_blank']").each(function() {
$(this).target = "_blank";
});
parent.find("a[rel='share']").click(function(event) {
var share_url = $(this).attr("href");
window.open(share_url, "Share", "width=768, height=450");
event.preventDefault();
});
}
function pageURL() {
if (currentAnchor != document.location.hash) {
currentAnchor = document.location.hash;
if (!currentAnchor) {
query = "section=home";
} else {
var splits = currentAnchor.substring(1).split("&");
var section = splits[0];
delete splits[0];
var params = splits.join("&");
var query = "section=" + section + params;
}
var content = $("#content");
$.get("loader.php", query, function(data) {
$("#load").fadeIn("fast");
content.fadeOut(100).html(data).fadeIn(500);
$("#load").fadeOut("fast");
});
pageEffects(content);
}
}
Thanks for the suggestions. I tried a few of them and they still did not lead to the desirable effects. After some cautious testing, I found out what was happening. With jQuery (and presumably Javascript as a whole), whenever an AJAX callback is made, the elements brought in through the callback are not binded to what was originally binded in the document, they must be rebinded. You can either do this by recalling all the jQuery events on a successful callback or by using the .live() event in jQuery's library. I opted for .live() and it works like a charm now and no more recursive errors :D.
$(document).ready(function() {
// Popup Menus
$(".bannerMenu").live("hover", function(event) {
if (event.type == "mouseover") {
$(this).find("ul.bannerSubmenu").slideDown(300);
} else {
$(this).find("ul.bannerSubmenu").slideUp(400);
}
});
// Rollover Content
$(".panel").live("hover", function(event) {
if (event.type == "mouseover") {
$(this).find(".panelContent").fadeIn(200);
} else {
$(this).find(".panelContent").fadeOut(300);
}
});
// HREF Events
$("a[rel='_blank']").live("click", function(event) {
var target = $(this).attr("href");
window.open(target, "_blank");
event.preventDefault();
});
$("a[rel='share']").live("click", function(event) {
var share_url = $(this).attr("href");
window.open(share_url, "Share", "width=768, height=450");
event.preventDefault();
});
setInterval("checkAnchor()", 500);
});
var currentAnchor = null;
function checkAnchor() {
if (currentAnchor != document.location.hash) {
currentAnchor = document.location.hash;
if (!currentAnchor) {
query = "section=home";
} else {
var splits = currentAnchor.substring(1).split("&");
var section = splits[0];
delete splits[0];
var params = splits.join("&");
var query = "section=" + section + params;
}
$.get("loader.php", query, function(data) {
$("#load").fadeIn(200);
$("#content").fadeOut(200).html(data).fadeIn(200);
$("#load").fadeOut(200);
});
}
}
Anywho, the page works as intended even in IE (which I rarely check for compatibility). Hopefully, some other newb will learn from my mistakes :p.

Categories