How to insert one final item after foreach in jquery? - javascript

I am fetching some json and returning it out, creating a new div for each object. I am now trying to add one final div (not from json) that just says something along the lines of 'This could be yours!'.
I have tried to insert
$('section#fans').append('<div class="fan">new div</div>');
or several variations of that (after, appendChild etc) and cannot get it to perform as i wish. Currently it adds one new div but before the foreach kicks in and it doesn't follow the fadeIn delay pattern that for the foreach does.
How can i get it to add the div with the same effect after the foreach. as one final div? As if it belonged to the json, altough it wont be the same template as the previous.
function get_fans(){
$.ajax('http://localhost/facebook_app/selectFans/', {
type : 'get',
dataType: 'json',
success : function (data) {
$.each(data, function(index) {setTimeout(function(){
var first_name = data[index].first_name;
var location = data[index].location;
var imagePath = data[index].image_path;
var d = $('<div class="fan"><img src="http://localhost/uploads/' + imagePath + '" width="170" height="160" />' + first_name + ', ' + location +'</div>');
$('section#fans').append(d);
d.hide();
d.fadeIn('50');
}, 250*(index +1));
});
$('section#fans').append('<div class="fan">new div</div>');
},
});
}

Your "final" insert is done immediately, while the other ones are done after a timeout.
You could replace
$('section#fans').append('<div class="fan">new div</div>');
with
setTimeout(function(){
$('#fans').append('<div class="fan">new div</div>');
}, 250*(data.length +2));
so that the final insert would be done after all others have been done.
A side note : don't use $('section#fans') but $('#fans'). This will be faster as jQuery will use the fast document.getElementById function.

Related

Check if a class or id exist in html response from ajax call

I know we can use hasClass() but in my case my ajax is returning html.
I can append then check the class exist or not but there'll be a flick. Is it possible to check what's inside the html before render it somewhere?
$.ajax({
url:'some_url',
success: function(html) {
// I can do this:
$('body').append(html);
if ($('my_selector').length > 0) {
// but I don't want to do this because I don't want that the html will show to the user
}
}
});
Yes, Possible
var yourReturnedHtml = getHtml();
return $(yourReturnedHtml).find('.someClass').length > 0;
Further #Mohammad Adil answer:
var html = '<div class="test">This is the response from the ajax call.</div>';
function simulateAjax(selector) {
var exist = $('<div />').html(html).find(selector).length > 0;
$('#result').append('The element "' + selector + '" ' + (exist ? '' : 'not ') + 'exist<br />');
}
simulateAjax('.test');
simulateAjax('.test1');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result"></div>
The difference between the answers, and I think that the reason it didn't work for you, that for example: If your response is <div class="test"></div>, the #Mohammad's script will return false because there is no element with the class .test in the main element in the response.
So, you should wrap the response with element, then you can use .find() to check.
Sure working method, used many time into my projects, This will help you find any elements, elements with some class or id.
You can append your ajax response to some hidden html element e.g div
e.g.
<div id="responseDiv" style="display: none"></div>
//Now write a function to save ajax response to div
//from this div, you can find out whether class or any element is there
$.ajax({
url: 'some url',
success: function(data){
//save response to div
$('#responseDiv').html(data);
//now to check whether some class exists in the div
if($('#responseDiv .class-to-find').length > 0){
//since class is found into ajax response, write your code here
}
}
});
i got your point now. Use the same approach of hasClass() in success function of ajax and using async parameter. To remove the flick, place your ajax code is seTimeOut with time 0 like
setTimeout(function(){ //Your ajax code here }, 0);

Having difficulty building a form summary with JS

Sorry for the noobish question but, I am trying to build a form summary that will populate a div (immediately) with all of the fields being used. Here is a small sample of the field: Fiddle
For some reason the JS is not working as I would expect it to, can anyone point out what I am doing wrong?
For example, I would like it to output: "AND name: john EXCEPT number 222".
I would also like to be able click on a result to remove it, and clear the field. Thank you
$(".allS").change(function () {
if ($(this).next('.textArea').not(':empty'))
// varible to hold string
var str = "";
$("select option:selected").each(function () {
str += $(this).text() + " ";
});
$("#text_here").text(str);
}).change();
$('.textArea').change(function(){
var $inputs = $('form#form :input[type="text"]'),
result = "";
$inputs.each(function(){
// access the individual input as jQuery object via $(this)
result += $(this).val()+"<br>";
});
// store result in some div
$('div#text_here').text(result);
}).change();
There were many mistakes in your code. I simplified it to a very short code that only does what's needed to get the output you requested. Here's the working fiddle.
$(".allS, .textArea").change(function () {
var str = '';
if ($('#name').val().length > 0 && $('#number').val().length > 0)
var str = $('#nameMod>option:selected').text() + ' name:' + $('#name').val() + ' ' + $('#numberMod>option:selected').text() + ' number ' + $('#number').val();
$("#text_here").html(str);
});
Basically, what this does is attach a change event handler to both classes (.alls, .textArea), and when the event is triggered, both input fields are tested for any content. If this test passes, a string is composed out of all the relevant values, and the div content is set. If the test failed (no content), the str variable contains an empty string and the div is cleared.
Just glancing at the code, the selector 'form#form :input[type="text"]' looks wrong. For starters, input is not a pseudoclass. Also, attribute matching shouldn't have the quotes.
This may or may not be what you want (I think it is, from looking at your html):
'form#form input[type=text]'
Also your <br>'s are not working because you called text(). call html() instead.

Elements prepended using jQuery .get() while looping through array are loaded in different order on page refresh

I want to show a subsection of some projects on my webpage. I have an array of project names and some corresponding data in html files, like in the example below. I have a button with some preview-content in it, and if a user clicks on that it opens up the full container with all the project details.
To do this I though to loop through a sliced array in reverse and prepend the code to a div element on my webpage. The content often loads fine, but sometimes when I refresh the page it will display the previews in a different order than as defined in the array. Also, sometimes "previewtitle" and "previewcontent" return undefined, but not all the time. What am I doing wrong here?
I want to prepend the projects dynamically in the same order on every refresh.
var $projectNames = [ "coolprojecthere", "andanotherone", "moreprojects", "lastone" ];
projects/coolprojecthere.html looks like this:
<div id="title">Project title here</div>
<div id="content">Content html here</div>
projects/previews/coolprojecthere.html looks like this:
<div id="title">Project title here</div>
<div id="content">Content text here</div>
I loop through them like this to prepend them:
$projectNames = $projectNames.slice(0, 7);
$.each($projectNames.reverse(), function (index, projectname) {
var previewtitle, previewcontent;
$.get("projects/previews/" + projectname + ".html", function (prevdata) {
previewtitle = $(prevdata).filter('#title').text();
previewcontent = $(prevdata).filter('#content').text();
});
$.get("projects/" + projectname + ".html", function (data) {
var project = "<section id=\"project\" class=\"\"> \
<t>" + previewtitle + "</t><br /> \
<p>" + previewcontent + "</p> \
</div> \
<div class=\"content\"> \
<h5>" + $(data).filter('#title').text() + "</h5> \
<div class=\"content-container\">"
+ $(data).filter('#content').html() +
"</div> \
</div> \
</section>"
$('#main-container').prepend(project);
});
From the jQuery Documentation you must specify async option to be set to false to get a synchronous AJAX request.
$.ajax({ url: 'projects/previews/" + projectname + ".html',
async: false,
dataType: 'json',
success: function(data) {
// your code here
}
});
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false.
Otherwise, you could also do the jQuery's AJAX setup, and set it in synchronous mode by calling once (above your initial code):
jQuery.ajaxSetup({async:false});
It will perform all your further AJAX calls in synchronous mode. You can continue using jQuery.get(); method as you did before.
Note: Please read Felix Kling's answer, about when synchronous calls might be a bad idea.
Making the Ajax calls synchronous is a bad idea. Instead, you should chain and nest them, so that each one is executed after each other.
Lets organize your code a little more, using promises:
function getPreviewData(projectName) {
return $.get(
"projects/previews/" + projectname + ".html"
).then(function(prevdata) {
return {
title: $(prevdata).filter('#title').text(),
content: $(prevdata).filter('#content').text()
};
);
}
function getProjectHTML(projectName, previewTitle, previewContent) {
return $.get("projects/" + projectname + ".html").then(function (data) {
// ...
});
}
$projectNames = $projectNames.slice(0, 7);
var head = new $.Deferred();
var chain = head.promise();
$.each($projectNames.reverse(), function (index, projectName) {
chain = chain.then(function() {
return getPreviewData(projectName).then(function(previewData) {
return getProjectHTML(projectName, previewData.title, previewData.content);
});
});
});
head.resolve();

jQuery: trying hook a function to the onclick when page loads

I have seen a similar question, HERE and have tried that, but I can't seem to get it working.
Here is my code for dynamically generating table rows.
for (var contribution = 0; contribution < candidate.contributions.length - 1; contribution++) {
var id = candidate.contributions[contribution].donor_id;
var uid = candidate.contributions[contribution].user_id;
$("#history-table").append(
"<tr onclick='" + parent.viewEngine.pageChange('public-profile', 1, id, uid) + ";>" +
"<td class='img-cell'>" +
"<img class='profile-avatar-small' src='/uploads/profile-pictures/" +
candidate.contributions[contribution].image + "' alt='' /></td><td class=''>" +
"<h2>" + candidate.contributions[contribution].firstname +
" " + candidate.contributions[contribution].lastname + "</h2></a><br/><br/>" +
"<span class='contribution-description'>" + candidate.contributions[contribution].contribution_description + "</span></td>" +
"<td><h3>$" + formatCurrency(candidate.contributions[contribution].contribution_amount) + "</h3></td></tr>");
}
This still executes the click event as soon as the page loads, which is not the desired behavior. I need to be able to click the tr to execute the click event.
Pass the whole thing as a string:
"<tr onclick='parent.viewEngine.pageChange(\'public-profile\', 1, " + id + ", " + uid + ");>" // + (...)
But, as you are using jQuery, you should be attaching the click handler with .on().
(I really don't recommend using inline event handlers like that, especially when you're already using jQuery, but anyway...)
The problem is that you need the name of the function to end up in the string that you are passing to .append(), but you are simply calling the function and appending the result. Try this:
...
"<tr onclick='parent.viewEngine.pageChange(\"public-profile\", 1, " + id + "," + uid + ");'>" +
...
This creates a string that includes the name of the function and the first couple of parameters, but then adds the values of the id and uid variables from the current loop iteration such that the full string includes the appropriately formatted function name and parameters.
Note that the quotation marks around "public-profile" were single quotes but that wouldn't work because you've also used single quotes for your onclick='...', so you should use double-quotes but they need to be escaped because the entire string is in double-quotes.
I'm wondering if you might be better simplifying things a bit.
If your rows are being dynamically added, then try putting some kind of meta-data in the <tr> tag, e.g. something like this:
<tr id="id" name="uid">
Then try the following with your jQuery (v.1.7 required):
$('#history-table tr').on('click', function(){
parent.viewEngine.pageChange('public-profile', 1, this.id, this.name);
});
This will likely require modification depending on how your page rendering works but it's a lot cleaner and easier to read having been removed from your main table markup.
Well that's because you're executing the function, not concatenating it. Try:
onclick='parent.viewEngine.pageChange("public-profile", 1, id, uid);'
Take this ->
$("#contribution-" + uid).click(function(){
parent.viewEngine.pageChange('public-profile',1, id, uid);
});
And do two things:
1) Move it outside of the 'for' statement
As soon as the for statement is executed, the click function will be executed as well. The click function is not being supplied as a callback function in this for statement.
2) Change it to ->
$("tr[id^='contribution-'").on('click', function(){
var idString = $(this).attr("id").split("-"); //split the ID string on every hyphen
var uid = idString[1]; //our UID sits on the otherside of the hyphen, so we use [1] to selec it
//our UID will now be what we need. we also apply our click function to every anchor element that has an id beginning with 'contribution-'. should do the trick.
parent.viewEngine.pageChange('public-profile',1, id, uid);
});
This is my solution.

jquery: "Exception thrown and not caught" in IE8, but works in other browsers

My code works fine in other browsers, but in IE8 I get "error on page" - and when I click that it says:
"Exception thrown and not caught Line: 16 Char: 15120 Code: 0
URI: http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"
I tried linking to jquery.js (rather than jquery.min.js) and to 1.5.1/jquery.min.js,
but problem still remains.
Can someone correct/improve my code for me, or guide me as to where to look. Thanks
<script type="text/javascript">
function fbFetch()
{
var token = "<<tag_removed>>&expires_in=0";
//Set Url of JSON data from the facebook graph api. make sure callback is set with a '?' to overcome the cross domain problems with JSON
var url = "https://graph.facebook.com/<<ID_REMOVED>>?&callback=?&access_token=" + token;
//Use jQuery getJSON method to fetch the data from the url and then create our unordered list with the relevant data.
$.getJSON(url, function(json)
{
json.data = json.data.reverse(); // need to reverse it as FB outputs it as earliest last!
var html = "<div class='facebook'>";
//loop through and within data array's retrieve the message variable.
$.each(json.data, function(i, fb)
{
html += "<div class='n' >" + fb.name;
html += "<div class='t'>" + (dateFormat(fb.start_time, "ddd, mmm dS, yyyy")) + " at " + (dateFormat(fb.start_time, "h:MMtt")) + "</div >";
html += "<div class='l'>" + fb.location + "</div >";
html += '<div class="i"><a target="_blank" title="opens in NEW window" href="https://www.facebook.com/pages/<<id_removed>>#!/event.php?eid=' + fb.id + '" >more info...</a></div>';
html += "</div >";
}
);
html += "</div>";
//A little animation once fetched
$('.facebookfeed').animate({opacity: 0}, 500, function(){
$('.facebookfeed').html(html);
});
$('.facebookfeed').animate({opacity: 1}, 500);
});
};
Does the code do the job in IE8 or does it break? The reason I ask is because if it works as expected you could just wrap it in a try{ } catch{ \\do nothing } block and put it down to another thing IE is rubbish at.
You may be better off creating an object for the creation of the facebook div. Something like...
var html = $('<div />');
html.attr('class', 'facebook');
Then in your each loop you can do this...
$('<div />').attr('class', 'n').append(fb.name).appendTo(html);
$('<div />').attr('class', 't').append etc...
Then append html to the facebookfeed object
Doing this may remove the scope for error when using single quotes and double quotes when joining strings together, which in turn may solve your issue in IE8
$('.facebookfeed').fadeOut(500, function(){
$(this).append(html).fadeIn(500);
});
Hope this helps!
UPDATE
The append method is used to add stuff to a jquery object. For more info see here
So to surround the div's as you mentioned in the comments you would do something like this...
var nDiv = $('<div />').attr('class', 'n').append(fb.name);
$('<div />').attr('class', 't').append(fb.somethingElse).appendTo(nDiv);
// etc
And then you would need to append that to the html div like so...
html.append(nDiv);
So that would give you
<div class="facebook">
<div class="n">
value of fb.name
<div class="t">
value of fb.somethingElse
</div>
</div>
</div>
So what you have done is created a new jquery object and appended to that, then appended that to the html object which you have then appended to the facebookfeed div. Confusing huh?!

Categories

Resources