This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
Purpose = toggle a section 'more info' for a specific item in a list
Problem = a simple jQuery .toggle() isn't working
Possible cause = getJSON loads to slow
I am loading a foursquare json to get venues around my current location. I then .append() those venues with jQuery to my HTML. After that I have a function to toggle a section with 'more info' on a click-event.
After some searching I think I found the problem. My getJSON starts loading and then my next function is loaded in jQuery. After this next function is loaded (which is my .toggle()) the getJSON finally finishes. So I think my function with my .toggle() can't find the classes to toggle, because they are not yet in my HTML because my getJSON isn't finished loading the data.
Here is my jQuery code.
And the output of my console in my browser has this order:
loaded 4sq venues line 29
toggle function loaded line 33
200 line 10
It's because of this meta.code on line 10 that I believe the getJSON is to slow loading...
I hope I made myself clear enough.
Thanks in advance
You should add your click event to body like
$('body').on('click', '.venueLabel', function(){
$(".venueMore").toggle("slow");
});
Because you add elements dynamically!
getJSON is going to be asynchronous. Which means it won't stop other Javascript from running while it's doing it's thing.
You should use a callback in getFoursquareVenues. Example below.
$(window).load(function() {
getFoursquareVenues(openDetailVenues());
});
function getFoursquareVenues(callback) {
$.getJSON("https://api.foursquare.com/v2/venues/search?client_id=placeholder&client_secret=placeholder&v=20130815&ll=51.0824401,3.714485&query=cafe", function(data) {
console.log(data.meta.code);
$('#venueList').html();
var content = '';
$.each(data.response.venues, function(index, elm) {
content += '' + '<div class="venue col-xs-12">' + '<div class="venueLabel" id="' + elm.id + '">' + elm.name + '</div>' + '<div class="venueMore">' + elm.location.address + elm.hereNow.count + '</div>' + '</div>'
});
$('#venueList').append(content);
if (callback) { callback() };
});
console.log('loaded 4sq venues');
}
function openDetailVenues() {
console.log('toggle function loaded');
$(".venueLabel").click(function() {
$(".venueMore").toggle("slow");
});
}
Related
I'm creating a template, now my search & navigation opens in a full screen popup when someone clicks the icon. I have setup two icons for this. & to handle the click request I've written the below code:
$(".demo-menu > a").on("click", function(){
$(this).parent().addClass('demo-show-menu');
});
$(".demo-menu-close").on("click", function(){
$('.demo-menu-close').closest('.demo-menu ').removeClass('demo-show-menu');
});
$(".demo-search > a").on("click", function(){
$(this).parent().addClass('demo-show-search');
});
$(".demo-search-close").on("click", function(){
$('.demo-search-close').closest('.demo-search ').removeClass('demo-show-search');
});
I'm still in learning stage of javascript. But I can understand that since both piece of codes for the icons are same, I can combine them in one to make the code look professional. Can someone tell me how can I achieve this?
You can export the adding of listeners to a method.
function addOnClickListeners(popup_type) {
$(".demo-" + popup_type + " > a").on("click", function(){
$(this).parent().addClass('demo-show-' + popup_type);
});
$(".demo-" + popup_type + "-close").on("click", function(){
$('.demo-' + popup_type + '-close').closest('.demo-' + popup_type + ' ').removeClass('demo-show-' + popup_type);
});
}
Notice: I replaced 'menu' with the method parameter popup_type.
You would then call the method with different parameters to register the listeners to different popups.
addOnClickListeners("menu");
addOnClickListeners("search");
Okay so I use a masonry script for arranging images in a grid, I placed it in a function arange_images() in an external script.
In my main script i call
$(document).ready(function(){
arange_images(); //<- Works lovely
});
Then i decide to load some other images with ajax. After that, my images stop being arranged.
function get_img(section_id) {
$.ajax({
type: 'GET',
url: './db/get_img.php',
data: {
section_id: section_id
},
success: function (data) {
var data_parsed = JSON.parse(data);
var images = '<div class="grid-sizer"></div><div class="gutter-sizer"></div>';
$.each(data_parsed, function (i, picture) {
images += '<div class="member">';
images += ' <img src="img/pictures/' + picture.path + '" alt="' + picture.alt + '"/>';
images += '</div>';
});
$('.grid').html(images);
arange_images(); //<- Does not work
}
});
}
$('.section_selector').click(function () {
get_img($(this).attr('data-section_id'));
arange_images(); //<- Does not work either
});
Searching similar errors did not help me.
Most of the problems with jquery after ajax are .click replaced with .on('click').
I read that I need to rebind jquery calls, but I don't really understand how to do it in this situation.
Your .click() handler will only bind elements that exist within the DOM at the time the document is ready. Since you need to bind to the elements after the ajax call, use .on().
Keep Calm and Call .on
$(document).on('click', '.section_selector'), function () {
get_img($(this).attr('data-section_id'));
});
The following .click()-method is fired in Chrome without problems.
In Internet Explorer it is only fired if I refresh the page (F5). If I access the page by entering the url (or redirected by a buttonclick from an other page) the .click-method is NOT fired.
But if I put an alert("?") before the .click() it works in IE too!
Why does it not work correctly in IE? I can't let the alert() be there...
$(window).load(function() {
//Fake click on the last used Tab
alert("?");
$("#"+GetCookie("lastTab["+window.location.pathname+"]")).click();
});
=> The available (clickable) tabs are created in
jQuery(document).ready(function($) {
...
});
EDIT From comments:
They are created inside the .read(function($) in this way:
$("#HillbillyTabs").append('<li>' + title + '</li>').after('<div id="Tab' + upperIndex + '"></div>');
After Container is created after the script:
<div id="tabsContainer"><ul id="HillbillyTabs"></ul></div>
Do not try to inject the function call, but rather add an event listener to the code. For example: (I made up some variables as your code did not indicate some things here)
var upperIndex = $('#tabsContainer').find('ul').length;
var title = "mytitle";
var newHeadId = 'TabHead' + upperIndex;
var newTabId = 'Tab' + upperIndex;
$("#HillbillyTabs").append('<li>' + title + '</li>').after('<div id="' + newTabId + '"></div>');
$("#HillbillyTabs").on('click', '#' + newHeadId, function() {
console.log(this.id);
SetCookie(this.id);
});
It seems IE does not recognize :
$(window).load()
You could try :
window.onload = function() {
$("#"+GetCookie("lastTab["+window.location.pathname+"]")).click();
};
Got the solution.
Curiously the fadeIn in the .load doesn't work for IE too (like the .click)
$(window).load(function() {
//Fake click on the last used Tab
alert("?");
$("#"+GetCookie("lastTab["+window.location.pathname+"]")).click();
// When the page has loaded in Chrome
$("#DeltaPlaceHolderMain").fadeIn(0);
});
For fading in I had to put the method immediately after the creation-method for the tabs (inside the .ready()) instead of the end of .ready().
There is now also the .click and it works now for IE.
jQuery(document).ready(function($) {
setTimeout(function() {
...
//Creation of tabs
$("#tabsContainer").tabs();
//Fake click on the last used Tab
$("#"+GetCookie("lastTab["+window.location.pathname+"]")).click();
// When the page has loaded in IE
$("#contentBox").fadeIn(0);
}, 0);
//.click NOT here
});
Thanks for your fast responses and tips!
Kind regards
I have been having problems with deep-linking when I want to make a back or forward recall to some php script that involves a query to my data base.
I think that whats happening is that when a link requires a php script that is on a deeper level it doesn't makes the callback to the server. It just works when it uses the same php script that uses the link that was displayed right back or after it.
This is my JS function:
function loadload(loc) {
$("document").ready(function(){
function loadURL(url) {
console.log("loadURL: " + url);
$(loc).load(url);
}
// Event handlers
$.address.init(function(event) {
console.log("init: " + $('[rel=address:' + event.value + ']').attr('href'));
}).change(function(event) {
$(loc).load($('[rel=address:' + event.value + ']').attr('href'));
console.log("change");
})
$('a').click(function(){
loadURL($(this).attr('href'));
});
});
};
This is my php echo line:
echo "<li><a onclick='loadload("."""."#txtHint".""".")' href="."'php/getdaimler.php?q=".$row['Program']."'"."rel="."'address:/Daimler/".$row['Program']."'>". $row['Program']. "</a></li><br>";
Also it makes my page become slower when several links have been triggered.
If there are some better functions or methods to use it would be great.
I'll appreciate your answers.
The posted jQuery Code can't work like this. First you use an inline event handler (onclick) inside the html code.
echo "<li><a onclick='loadload("."""."#txtHint".""".")' href="."'php/getdaimler.php?q=".$row['Program']."'"."rel="."'address:/Daimler/".$row['Program']."'>". $row['Program']. "</a></li><br>";
The method you call is loadload, the parameter is "#txtHint" which is used as a jQuery selector, but will never match any DOM Element. My best guess is, you want to load the server answer to an element with the id 'txtHint', in that case the selector would be: #txtHint.
Now to the jQuery/ javascript function itself:
function loadload(loc) {
// this is wrong, you can not use the event handler for dom ready here...
$("document").ready(function(){
function loadURL(url) {
console.log("loadURL: " + url);
$(loc).load(url);
}
// Where does $.address come from?....
// Event handlers
$.address.init(function(event) {
console.log("init: " + $('[rel=address:' + event.value + ']').attr('href'));
}).change(function(event) {
$(loc).load($('[rel=address:' + event.value + ']').attr('href'));
console.log("change");
})
// and here you'll define another click handler - inside the click handler
// will never be executed...
$('a').click(function(){
loadURL($(this).attr('href'));
});
});
};
Either you use the inline event handler, or a general bind logic, do not mix it.
Variant a: inline event handler
function loadload(loc,url) {
console.log("loadURL: " + url);
$(loc).load(url);
}
echo "<li><a onclick='loadload(\"#txtHint\",\"php/getdaimler.php?q=".$row['Program']."\")' href='php/getdaimler.php?q=".$row['Program']."' rel='address:/Daimler/".$row['Program']."'>". $row['Program']. "</a></li><br>";
Variant b: general binding:
$("document").ready(function(){
$('a.loadload',function() {
$('#txtHint').load($(this).attr('href'));
});
});
echo "<li><a class='loadload' href='php/getdaimler.php?q=".$row['Program']."' rel='address:/Daimler/".$row['Program']."'>". $row['Program']. "</a></li><br>";
So far for your javascript / html code. To be honest I have no idea if this fits your 'deep link' question, or the db-query you talked about, but it might be a starting point.
I'm trying to use AJAX to dynamically generate a JquerUI Accordion based on what is selected in a box. Currently I have
<div style="display:none" id="testselect">
</div>
With JS
$("#courseselect").change(function () {
$("#testselect").html(""); // Empty any previous data
$("#testselect").css("display", "block"); // Display it if it was hidden
$.getJSON('json.php?show=tests&courseid=' + $(this).val(), function(data) {
for(x in data)
{
$("#testselect").append("<h3 value=\"" + data[x].uno + "\">" + data[x].name + "</h3>");
$("#testselect").append("<div>Foo</div>");
}
$("#testselect").accordion({ change:function(event, ui) { courseid = ui.newHeader.attr("value");
} });
});
});
Now this works the first time I change my selection, but after that it reverts to plain old unformatted HTML. As if the call to .accordion() was never done. I'm guessing this has something to do with JQuery not wanting me to format something twice, but I really have no idea.
Try to destroy the accordion before you empty the div and start again:
$("#courseselect").change(function () {
$("#testselect")
.accordion("destroy")
.empty() // equivalent to .html("");
$.getJSON(...
More info here.
Good luck!