jQuery load script executes many times - javascript

I have a simple method which loads content and should replace it into an div element:
$("a[data-ajax='true']").on('click', function (event) {
event.preventDefault();
var goToLink = this.href;
animateLink(this);
$('#ajax-target').fadeTo(0.2, 0.5, function () {
lastLink = currentLink;
currentLink = goToLink;
$('#ajax-target').load(goToLink, {}, function () {
$('body').scrollTop(0);
$('#ajax-target').fadeTo('slow', 1);
});
});
});
Now I load per ajax HTML code which contains the following code:
<script>
console.log('Running...')
</script>
First time I click on my link which loads the ajax, I see 'Running...' on the console as expected. Second time I do so, 'Running...' is printed twice on the console. Third time this message I get 4 times on the console, and so on. I can't figure out where the problem is. When I load the HTML code per ajax request and replace it per html() method, same problem. Has someone a idea what's wrong?
Edit
After the answer here I have now the following code which works:
<script>
var currentLink, lastLink;
function animateLink(obj) {
var el = $(obj);
var animate = el.attr('data-animation');
if (animate != undefined) {
animate = animate.toLowerCase();
animate = animate == 'false' ? false : true;
} else {
animate = true;
}
if (animate) {
el.toggle('explode');
}
}
$(document).ready(function () {
$("a[data-ajax='true']").on('click', function (event) {
event.stopImmediatePropagation();
event.preventDefault();
var goToLink = this.href;
animateLink(this);
$('#ajax-target').fadeTo(0.2, 0.5, function () {
lastLink = currentLink;
currentLink = goToLink;
$('#ajax-target').load(goToLink, {}, function () {
$('body').scrollTop(0);
$('#ajax-target').fadeTo('slow', 1);
});
});
});
});
function historyBack() {
$('#ajax-target').fadeTo(0.2, 0.5, function () {
var newLink = lastLink;
lastLink = this.href;
currentLink = newLink;
$.get(newLink, {}, function (response) {
$('body').scrollTop(0);
$('#ajax-target')
.html(response)
.fadeTo('slow', 1);
});
});
}
</script>
This is located on the site directly. This part is not removed when the ajax request is done. The part which is always changed is the following:
<div class="content-wrapper" id="ajax-target">
#Html.Partial("LayoutContentHeader")
<section class="content">
#RenderBody()
</section>
</div>
The loaded page is an MVC page, where the main-frame does not contain any HTML or BODY tag, only the content which needs to get replaced and in addition sometimes scripts (how my script above):
#if (IsAjax)
{
if (isMainLayout)
{
#Html.Partial("LayoutContentHeader")
<section class="content">
#RenderBody()
</section>
}
else
{
#RenderBody()
}
<script>
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
</script>
}
As you can see, when we are in a ajax request, I only send the important content.
And the code of a pressed link is for example:
<a href="/wilhelmshaven/hse/" data-ajax="true" class="btn btn-block btn-social" style="color: white !important; background-color: rgb(243,156,18)">
<i class="fa fa-th"></i>HSE
</a>
with no link around (which can force bubbling).

Try adding this code
$("a[data-ajax='true']").on('click', function (event) {
event.stopImmediatePropagation();
var goToLink = this.href;
animateLink(this);
$('#ajax-target').fadeTo(0.2, 0.5, function () {
lastLink = currentLink;
currentLink = goToLink;
$('#ajax-target').load(goToLink, {}, function () {
$('body').scrollTop(0);
$('#ajax-target').fadeTo('slow', 1);
});
});
});
Reference : http://api.jquery.com/event.stopimmediatepropagation/

Related

jQuery/JS Resize of iframe not working

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);
}

How to execute jquery function one after other

In below, When i click on button call the jquery click event,It will first shows the alerts upto this it works properly, In this i have call two functions(i.e. reload() and popup()) when i click on button it gives alerts and after that it execute popup() function and reload() function at a time.
My query is i want to execute first reload function(it reload only once) then execute popup function means when i click on button first reload the page only once and then show me my popup.
<script>
$(document).ready(function()
{
$('.button').click(function()
{
var href = $(this).val();
alert(href);
$.session.set("linkurl",href);
alert($.session.get('linkurl'));
//window.location.reload();
function reload()
{
if(document.URL.indexOf("#")==-1)
{
// Set the URL to whatever it was plus "#".
url = document.URL+"#";
location = "#";
//Reload the page
location.reload(true);
return true;
}
}
function popup()
{
document.getElementById('light').style.display='block';
document.getElementById('fade').style.display='block';
}
$.when( reload() ).done(function() {
popup();
});
});
});
</script>
<button class="button" value="<?php echo $value['3']; ?>" style="background-color:#ff8c21;">Buy Now</button>
try something like this:
function reload() {
if (document.URL.indexOf("#") == -1) {
// Set the URL to whatever it was plus "#".
url = document.URL + "#";
location = "#";
//Reload the page
location.reload(true);
return true;
}
function popup() {
document.getElementById('light').style.display = 'block';
document.getElementById('fade').style.display = 'block';
}
if($.session.set("reload") == true ) {
popup();
$.session.set("reload", false);
}
$('.button').click(function() {
$.session.set("reload", true);
reload();
});
The simple answer - it will not work. You cannot reload a page and execute any JavaScript after it. After unloading a page, JavaScript will stop executing.
You need to pass any sort of flag to your target page in order to tell it to show a popup. You can use GET parameters, for example.
There is a good Stackoverflow article on this topic:
Global Variable usage on page reload
$(document).ready(function() {
$('.button').click(function() {
var href = $(this).val();
alert(href);
$.session.set("linkurl", href);
alert($.session.get('linkurl'));
//window.location.reload();
reload(function () {
popup();
});
});
});
function reload(callback) {
if (document.URL.indexOf("#") == -1) {
// Set the URL to whatever it was plus "#".
url = document.URL + "#";
location = "#";
//Reload the page
location.reload(true);
return true;
}
}
function popup() {
document.getElementById('light').style.display = 'block';
document.getElementById('fade').style.display = 'block';
}

Need to disable anchor scroll in AJAX code

https://jsfiddle.net/JTBennett/ekc6yobw/
Here's my current jQuery code:
var rel = "";
var menuUp = true;
$('.navButton').click(function () {
rel = $(this).attr('rel');
menuUp = false;
window.location.hash = rel;
$('#mainContainer').scrollTop(0);
});
$('.resetButton').click(function () {
window.location.hash = "";
menuUp = true;
});
function navigate() {
$('#mainMenu').animate({
opacity: 0,
left: '100%'
}, function () {
$(rel).animate({
top: '0px'
});
});
};
function resetNav() {
$(rel).animate({
top: '110%'
}, function () {
$('#mainMenu').animate({
opacity: 1,
left: '0px'
});
});
};
window.onhashchange = function () {
if (menuUp) {
resetNav();
} else {
navigate();
}
};
I'm attempting to disable the scrolling up to the top of the page on click. I've never done any manipulation of hashes until now...figured I'd better jump on the AJAX bandwagon.
Anyway, I've tried quite a few methods without success (links below).
The most hopeful candidate was this piece of code:
var elems = document.getElementsByClassName('mainContainer');
for (var i=0; i<elems.length; ++i) {
//add click function to each element
elems[i].addEventListener('click', clickFunc);
}
var keepScroll = false;
function clickFunc(e) {
e.preventDefault();
history.replaceState({}, '', e.target.href);
}
I placed it as a separate header script, got no relief. I'm sure the issue is related to the AJAX code relying on the hashes for commands, but I don't know why I can't disable the default action still. If anyone can fork my jsfiddle and find what's wrong, I'd greatly appreciate it.
-Joel
[1]: http://stackoverflow.com/questions/3659072/how-to-disable-anchor-jump-when-loading-a-page
[2]: http://stackoverflow.com/questions/10626814/avoid-the-page-scrolling-jumping-when-anchor-is-in-the-url
[3]: http://jsbin.com/IKoRiTeS/2/edit?html,css,js,output

How to SlideUp div when clicked in jQuery

I have the following simple demo here: https://tinker.io/8e585/1. I have attached code below.
Initially, the contents of both 'Test 1' & 'Test 2' are closed.
However, when clicked, they open. I would like it, if when one is open and then clicked it closes. So, if open AND clicked = close. Is this possible?
Many thanks for any helpers with this :-)
..
HTML
<div class="grid_4">
<h2 style="margin-bottom:4px">Test 1</h2>
<div class="newboxes2" id="newboxes6">
<p>bla 1</p>
</div>
</div>
<div class="grid_4">
<h2 style="margin-bottom:4px">Test 2</h2>
<div class="newboxes2" id="newboxes7">
<p>bla 2</p>
</div>
</div>
CSS
.newboxes2 {display:none}
jQuery
function slideonlyone(thechosenone) {
$('.newboxes2').each(function(index) {
if ($(this).attr("id") == thechosenone) {
jQuery(this).parent('.grid_4').children().find('img.small').attr('src', '/wp-content/themes/boilerplate/images/image_corner_btn_onstate.png');
$(this).slideDown(200);
}
else {
jQuery(this).parent('.grid_4').children().find('img.small').attr('src', '/wp-content/themes/boilerplate/images/image_corner_btn_offstate.png');
$(this).slideUp(600);
}
});
}
You can simply use a class to do it:
https://tinker.io/8e585/12
function slideonlyone(thechosenone) {
$('.newboxes2').each(function(index) {
if (this.id == thechosenone) {
if($(this).is('.active') )
$(this).removeClass('active').slideUp(600);
else
$(this).addClass('active').slideDown(200);
}
else
$(this).removeClass('active').slideUp(600);
if($(this).is('.active') )
jQuery(this).parent('.grid_4').children().find('img.small').attr('src', '/wp-content/themes/boilerplate/images/image_corner_btn_onstate.png');
else
jQuery(this).parent('.grid_4').children().find('img.small').attr('src', '/wp-content/themes/boilerplate/images/image_corner_btn_offstate.png');
});
}
everything should be a lot easier then you think. you should remove your inline javascript event-handler. and use the jquery-toggle-mechanism:
then your javascript code could become as short as this:
$('.grid_4').bind('click', function () {
$(this).find('.newboxes2').slideToggle(200);
});
see the updated tinker for an example: https://tinker.io/8e585/4
if you want your slideDown to be faster (200) than your slideUp (600), you could lookup the current display property:
var duration, $newboxes2;
$('.grid_4').bind('click', function () {
$newboxes2 = $(this).find('.newboxes2');
duration = $newboxes2.css('display') === 'none' ? 200 : 600;
$(this).find('.newboxes2').slideToggle(duration);
});
tinker thats working here: https://tinker.io/8e585/5
code with your imageswap. this code could even be 1 or 2 lines shorter (the if-else), but i leave it like that, to make it easier to read for you:
var duration, $newboxes2, imgSrc, imgBase = '/wp-content/themes/boilerplate/images/';
$('.grid_4').bind('click', function () {
$newboxes2 = $(this).find('.newboxes2');
if ($newboxes2.css('display') === 'none') {
duration = 200;
imgSrc = imgBase + 'image_corner_btn_onstate.png';
} else {
duration = 600;
imgSrc = imgBase + 'image_corner_btn_offstate.png';
}
$(this).find('img.small').attr('src', imgSrc);
$(this).find('.newboxes2').slideToggle(duration);
});
see tinker: https://tinker.io/8e585/13
Sounds like you want an accordion: http://jqueryui.com/accordion/ alternatively, you could use the Javascript below (remove the inline Javascript you have in your HTML and just use '#'):
(function($) {
$(function() {
var links = $('.grid_4 h2:first-child a');
links.addClass('closed');
links.click(function() {
var $this = $(this);
links.each(function() {
var curLink = $(this);
if(curLink !== $this) {
curLink.parents('.grid_4').find('.newboxes2').slideUp(600, function({curLink.addClass('closed');});
curLink.parents('.grid_4').find('img.small').attr('src', '/wp-content/themes/boilerplate/images/image_corner_btn_offstate.png');
}
});
if($this.hasClass('closed')) {
$this.parents('.grid_4').find('.newboxes2').slideDown(200, function() {$this.removeClass('closed');});
$this.parents('.grid_4').find('img.small').attr('src', '/wp-content/themes/boilerplate/images/image_corner_btn_onstate.png');
} else {
$this.parents('.grid_4').find('.newboxes2').slideUp(600, function() {$this.addClass('closed');});
$this.parents('.grid_4').find('img.small').attr('src', '/wp-content/themes/boilerplate/images/image_corner_btn_offstate.png');
}
});
});
})(jQuery);

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