I know this kind of question has been asked before, but the general solution of
$($("input").get().reverse()).each(function() { /* ... */ });
is not working for me. I have an xml document that contains a list of concerts that I'd like to display on a webpage. So, in JQuery:
$.ajax({
type: "GET",
url: "concerts.xml",
dataType: "xml",
cache: false,
success: function(xml) {
$(xml).find('concert').each(function() {
/*do stuff*/
});
}
});
However, I'd like to display the concerts in reverse order. So, I tried the following, but it did not work:
$.ajax({
type: "GET",
url: "concerts.xml",
dataType: "xml",
cache: false,
success: function(xml) {
$($(xml).find('concert').reverse()).each(function() {
/*do stuff*/
});
}
});
Any assistance would be much appreciated. Thanks.
You excluded the call to the get()[docs] method.
// --------------------v
$($(xml).find('concert').get().reverse()).each(function() {
This is needed to get an Array of the elements from the jQuery object. This is what allows you to call .reverse(), which is on Array.prototype.
To walk through the items in reverse order, why not just use code like this:
var data = $("input");
for (var i = data.length - 1; i >= 0; i--) {
var item = data[i];
// do whatever you want to do with item here
}
Or, if you want to make a function out of it that takes a jQuery object and your function:
function reverseEach(jQueryObj, fn) {
for (var i = jQueryObj.length - 1; i >= 0; i--) {
if (fn.call(jQueryObj[i], i, jQueryObj[i]) === false) {
break;
}
}
}
So, you could then call:
reverseEach($(xml).find('concert'), function() {
// do stuff here
});
or:
reverseEach($("input"), function() {
// do stuff here
});
Or, you could even make reverseEach a jQuery plugin if you wanted.
Related
I'm trying to make a notification system that gets data every 5 secs but I don't know why it doesn't work properly. It outputs the notification endlessly but it should get the data and compare it to the last data it stored and if the data is not the same it should append the notification(s) and when it's the same it should alert "same".
var appliedData;
setInterval(getNotifications, 5000);
function getNotifications(){
$.ajax({
type: 'GET',
url: 'includes/socialplatform/friendsys/notifications.inc.php',
dataType: "json",
async: false,
success: function(data) {
if ( appliedData != data ) {
appliedData = data;
for(i=0; i < data.length; i++){
$( ".notification-container" ).append('<div class="notification"><p>' + data[i].user + '</p></div>');
}
}else{
alert("sammee");
}
}
});
}
Objects (any non-primitive: an array is an object) will never be equal to each other unless they reference the same place in memory. When comparing, your appliedData will always be different from your data, so that condition will always fail. If the response strings can be guaranteed to be the same when they represent the same object, you can simply compare the strings, as shown below. If not, you'll have to carry out a deep comparison instead.
let lastDataStr;
setInterval(getNotifications, 5000);
function getNotifications() {
$.ajax({
type: 'GET',
url: 'includes/socialplatform/friendsys/notifications.inc.php',
dataType: "text", // change here, then parse into an object in success function
async: false,
success: function(newDataStr) {
if (newDataStr === lastDataStr) {
alert('same');
return;
}
lastDataStr = newDataStr;
const newData = JSON.parse(newDataStr);
newData.forEach(({ user }) => {
$(".notification-container").append('<div class="notification"><p>' + user + '</p></div>');
})
}
});
}
I am using JQuery UI for autocompletion where I take input and ping a server with that input and end create an array to be given to the source of autocomplete. Right now it works perfect sometimes, but when i print the people array sometimes not all the source data shows up on the screen that is shown in console.
let input =$("<input type='text'/>")
.appendTo('#dynamic-form-elements');
input.autocomplete({
source: [] // Initially empty
}).on('input', function () {
$.ajax({
url: "https://lookmeup/json/person/" + input.val(),
dataType: "json",
success: function (parsed_json) {
let people = [];
let results = parsed_json.data;
for (i = 0; i < results.length; i++) {
people.push(results[i][1])
}
console.log(people)
input.autocomplete('option', 'source', people);
}
});
})
You need to include the "minLength:" attribute in the autocomplete so it waits til you hit the minimum length before it performs the ajax.
You can see this in use here:
https://jqueryui.com/autocomplete/#remote-jsonp
The final code should look like this:
input.autocomplete({
source: function(req, response) {
$.ajax({
url: "https://lookmeup/json/person/" + req.term,
dataType: "json",
success: function (parsed_json) {
// do the stuff here and call response callback
}
});
},
minlength: 3
})
You should do this, use source as function: https://jqueryui.com/autocomplete/#remote
input.autocomplete({
source: function(req, response) {
$.ajax({
url: "https://lookmeup/json/person/" + req.term,
dataType: "json",
success: function (parsed_json) {
// do the stuff here and call response callback
}
});
}
})
I have an each() loop in my AJAX handler to do push into my temp array, but in the end I still get an empty array. It's strange, I remember I once use promise on each() so it has no problem.
var temp = [];
$.ajax({
type: 'GET',
url: '/endpoint',
success: function(data) {
$(data).each(function() {
//do some stuff
console.log(something); // working
temp.push(something);
}).promise().done(function() {
console.log(temp); // still empty array?!
});
});
update: here's how people has done it https://stackoverflow.com/a/8941358/7095330
Reducing your script to what your question is asking, everything seems to be working fine. Hopefully this will help you find out that your problem is somewhere else in your code:
var temp = [];
var data = [1,2,3,4,5,6,7,8];
$(data)
.each(function(thing) {
//do some stuff
console.log(thing); // working
temp.push(thing);
})
.promise()
.done(function() {
console.log(temp); // still empty array?!
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
However the promise().done() is pretty weird; I can't see why you'd need that there.
Sounds like a case for map, where you have an input array and you want to transform its contents.
var data = [1,2,3,4,5,6,7,8]
var changedData = data.map(function (datum) {
// do stuff
return 'did stuff to ' + datum;
});
console.log(changedData)
Unless what you were trying to do was the following, which still works. PEBKAC error perhaps?
var temp = [];
$.ajax({
type: 'GET',
url: 'https://google.com/',
// replaced success: with error:, for example's sake
error: function(data) {
$(data).each(function() {
//do some stuff
console.log('something');
temp.push('something');
}).promise().done(function () {
console.log('each done', temp);
});
},
done: function() {
console.log('ajax done:', temp);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You forgot a bracket }
var temp = [];
$.ajax({
type: 'GET',
url: '',
success: function(data) {
$(data).each(function() {
//do some stuff
console.log('something'); // working
temp.push('something');
}).promise().done(function() {
console.log(temp); // still empty array?!
});
}});
see https://jsfiddle.net/gw10un58/
I am trying to use global variables as flags and cant get it to work. I have two functions:
This function sets a flag to be false when it is done.
function buildYearsTable(btn) {
//console.log ("At build years table")
var fundCode = document.getElementById("fundCode").value
buildYearsFlag = true;
$.ajax({url: "/scholarship/scholarshipMaintenance/buildYearsTable", method: "POST",
cache: false, data: {fundCode: fundCode},
complete: function(xhr, statusCode){
console.log("inside build years table")
data = $.parseJSON(xhr.responseText)
$('#myTable tbody').html('');
data = data.sort()
data = data.reverse()
for(var i = data.length - 1; i >= 0; i--) {
moveYearOption(data[i])
addYearRow(data[i])
}
buildYearsFlag = false;
//$('#yearsTable').html(xhr.responseText)
console.log("done in build years table")
}})
}
This function is called when the first one is called, but i need it to perform its ajax call ONLY once the flag is set to false by the first function. I am not sure how to accomplish this. I was thinking a while loop (polling kind of idea) but not sure how to go about it.
function rebuildYearSelects(btn) {
//console.log ("At rebuild selects")
var fundCode = document.getElementById("fundCode").value
while (buildYearsFlag == false) {
$.ajax({url: "/scholarship/scholarshipMaintenance/rebuildYearSelects", method: "POST",
cache: false, data: {fundCode: fundCode},
complete: function(xhr, statusCode){
console.log("got inside rebuild years select")
data = $.parseJSON(xhr.responseText)
selectedYears = data.sortedSelectedYears
unselectedYears = data.sortedUnselectedYears
$('#yearsModal').replaceWith(data.html)
fixModals();
buildYearsFlag = true;
console.log("done in rebuildYearSelects")
}})
}
}
The best way to accomplish this is by using callbacks.
You just need to call the second function after the response from the first.
You should use 'done' instead of 'complete'.
function buildYearsTable(btn) {
var fundCode = document.getElementById("fundCode").value
$.ajax({url: "/scholarship/scholarshipMaintenance/buildYearsTable", method: "POST",
cache: false, data: {fundCode: fundCode},
done: function( data ){
// Your code goes here
// Call the function only after the response
rebuildYearSelects();
}})
}
Html:
onclick="buildYearsTable();"
Remove the flags and the while loop, everything should work.
I want to solve once for all the problem of looping ajax request and passing 'index' into it (the problem below):
for (var index = 0; index < 4; index++) {
$.ajax({
url: 'http://graph.facebook.com/',
dataType: 'jsonp',
success: function(json) {
console.log(json[index]);
}
});
}
in this code within every 'success' callback 'index' will be 3. But I want to invoke callback with 0, 1, 2, 3. Many people are placing ajax request within a closure:
for (var index = 0; index < 4; index++) {
(function(index){$.ajax({
url: 'http://graph.facebook.com/',
dataType: 'jsonp',
success: function(json) {
console.log(json[index]);
}
});
})(index);
}
what in my opinion is a huge mistake - what if the request won't be there at the time? Than 'json' variable will be 'undefined'.
Does any of You guys have some proper way to solve this issue?
Actually the JSON will not be undefined.
If you would break the following code apart it would become more clear:
So instead of this:
for (var index = 0; index < 4; index++) {
(function(index){$.ajax({
url: 'http://graph.facebook.com/',
dataType: 'jsonp',
success: function(json) {
console.log(json[index]);
}
});
})(index);
}
...you can also write it like this:
function myFunction(index) {
$.ajax({
url: 'http://graph.facebook.com/',
dataType: 'jsonp',
success: function(json) {
console.log(json[index]);
}
});
}
// and call it like this
for (var index = 0; index < 4; index++) {
myFunction(index);
}
As you might already see, how are any of those two variables going to change by another call while they are defined inside the function?
(On a side note: I think it actually looks cleaner this way)