I'm using an AJAX request (with jQuery) to retrieve data from a XML file. I was wandering what is the best way to sort the result in a specific order before printing them on the page.
the problem is that I'm calculating a distance between a starting position and the
position of every item in the XML and then append that distance (in jQuery) to each item.
Everything is working except the items are listed on the page related to their order in the original XML.
Now, what I would like to do is to sort this list from the smallest distance to the biggest before adding them to the page...
Is there any sort of "sort-by" of "order-by" function in jQuery/AJAX (or does that make any sense)?
So far, here's what I have:
$.ajax({
type: "GET",
url: "blc.xml",
dataType: "xml",
success: parseXml
});
function parseXml(xml) {
$(xml).find("marker").each(function() {
var transit = $(this).find("transit").text();
var type = $(this).find("type").text();
var codepostal = $(this).find("codepostal").text();
var lat2 = $(this).find("lat").text();
var lng2 = $(this).find("lng").text();
var maxDist = 10;
if (newLatLon < maxDist) {
$("#list").append('<p id="' + transit + '">' + type + codepostal + '</p>');
$("#" + transit).append(document.createTextNode(" " + newLatLon + " KM"));
}
Thanks for your input!
(Please not that I don't want to be able to drag items in any order (as with jQuery UI), just to print them in a specific order).
Tablesorter is a jquery plug-in for building sortable tables. There are many, take your pick.
Can you just use the JavaScript function sort()?
function sortNumber(a,b)
{
return a - b;
}
var n = [10, 5, 40, 25, 100, 1];
var sorted = n.sort(sortNumber)
// sorted = [1, 5, 10, 25, 40, 100]
EDIT: Added sortNumber function.
Related
I'm calling an ajax for giphy, with this code:
$.ajax({
url: queryURL,
method: "GET"
}). then(function(response) {
console.log(response);
when I look at the console log there's an object with the first property being data. Each index of data is another object, inside this object are two properties i'm trying to pull, rating and url. I want to be able to list the rating and url not just of a specific index, but every index in that data array. What would be the best way to do that? Currently I've tried a for loop
for (var i = 0; i<response.data.length;i++){
var dataIndex = response.data[i];
}
then <creating a variable something like>
var imgURL = response.data[dataIndex].url
but its not working.
Here's the entire code
function displayTopicGif() {
var topic = $(this).attr("data-name");
// query url
var queryURL = "https://api.giphy.com/v1/gifs/search?q=" + topic + "&limit=20&rating=r&api_key=";
$.ajax({
url: queryURL,
method: "GET"
}).then(function (response) {
console.log(response);
// for loop to create a variable for the index of the objects data
for (var i = 0; i < response.data.length; i++) {
var dataIndex = response.data[i];
}
// where the gif's will be dumped
var topicDiv = $("<div class='topic'>");
// rating of gif
var rating = response.data[0].rating;
console.log(rating);
// Creating an element to have the rating displayed
var pOne = $("<p>").text("Rating: " + rating);
// add to the rating element
topicDiv.append(pOne);
// retrieve the IMG of the gif
var imgURL = response.data[0].url;
var image = $("<img>").attr("src", imgURL);
topicDiv.append(image);
// put gif into topic-view div
$("#topic-view").prepend(topicDiv);
});
}
You can check that something is an object using $.isPlainObject and then read through its properties via:
for (key in object) {
var value = object[key];
//log
}
Or you can get the keys using Object.getOwnPropertyNames();. See this sample excerpt from MDN:
const object1 = {
a: 1,
b: 2,
c: 3
};
console.log(Object.getOwnPropertyNames(object1));
// expected output: Array ["a", "b", "c"]
I am working on a sort of aggregator/tweet wall. At the mo it only uses data from an XML file (of our latest news). I made a bit of a mistake in the logic, though.
At present it only pulls items from the last 30 days. Live demo takes a few secs to load (using last 240 days for extra content to work with). However, I need it to:
Pull the last 4 items in chrono order.
Shuffle that array so they are
random ordered (but will all be "fresh" news).
Output that array.
jQuery(function () {
$.ajax({
url: 'http://www.sagittarius-digital.com/news.rss',
dataType: 'xml',
complete: function() {
/*Init masonry.js*/
var container = document.querySelector('#container');
var msnry = new Masonry( container, {
// options
gutter: 20,
columnWidth: 320,
itemSelector: '.item'
});
}
}).done(function (xml) {
var items = [];
$(xml).find('item').each(function () {
var $item = $(this);
var date = new Date($item.find('pubDate').text());
var date_30 = new Date().getTime() - (1000*60*60*24*240); /* last figure = number of days to sort back from */
var yyyymmdd = date.getFullYear() + '' + (date.getMonth() + 1) + '' + date.getDate();
if ( date_30 < date.getTime() ) { // newer than 30 days
var array = '<div class="item"><h2>News</h2>';
array += '<p>' + yyyymmdd + '</p>';
array += '<a href="' + $item.find('link').text() + '">';
array += '<h2>' + $item.find('title').text() + '</h2>';
array += '<p>' + $item.find('description').text() + '</p>';>
array += '<p>Category: ' + $item.find('category').text() + '</p>';
array += '</a>';
array += '</div>';
items.push(array);
}
});
$('div.item').after(items.join(' '));
}).fail(function () {
console.log('error', arguments)
});
});
Basically after that I need to add a second RSS feed with different info doing the same, a Twitter ajax call and facebook ajax call. So I will have 12 bits of data that are all the 4 "freshest", these will then shuffle into a random order and output, so there is a nice even mix.
I try to implement AJAX posts loop for WordPress from Tuts+
I want this loop to show under comments form in single post page in three columns (each for another category)
In single.php I have divs (numbers comes from category):
<div class="news_posts-6"></div>
<div class="news_posts-3"></div>
<div class="news_posts-2"></div>
My ajaxLoop:
jQuery(function($){
var page = 1;
var loading = true;
var $window = $(window);
var cat = [6,3,2];
var load_posts= jQuery.each(cat, function(){
var $content = $(".news_posts-" + this);
$.ajax({
type : "GET",
data : {numPosts: 2, pageNumber: page, cat: this},
dataType : "html",
url : "http://127.0.0.1:4001/wordpress/wp-content/themes/twentyeleven-child-theme/loopHandler.php",
beforeSend : function(){
if(page != 1){
$content.append('<div id="temp_load" style="text-align:center">\
<img src="/images/ajax-loader.gif" />\
</div>');
}
},
success : function(data){
$data = $(data);
if($data.length){
$data.hide();
$content.append($data);
$data.fadeIn(500, function(){
$("#temp_load").remove();
loading = false;
});
} else {
$("#temp_load").remove();
}
},
error : function(jqXHR, textStatus, errorThrown) {
$("#temp_load").remove();
alert(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
});
$window.scroll(function() {
var content_offset = $content.offset();
console.log(content_offset.top);
if(!loading && ($window.scrollTop() +
$window.height()) > ($content.scrollTop() + $content.height() + content_offset.top)) {
loading = true;
page++;
load_posts();
}
});
load_posts();
});
Part of loopHandler.php:
$numPosts = (isset($_GET['numPosts'])) ? $_GET['numPosts'] : 0;
$page = (isset($_GET['pageNumber'])) ? $_GET['pageNumber'] : 0;
$cat = (isset($_GET['cat'])) ? $_GET['cat'] : 0;
echo $numPosts;
echo $page;
query_posts(array(
'posts_per_page' => $numPosts,
'paged' => $page,
'cat' => $cat
));
I tried use simple array containing categories numbers but it doesn't work. Depends on
data : {numPosts: X, pageNumber: page, cat: this},
there is X post displaying in each column (same posts from first category).
I guess I need to use JSON, which I tried, but it was total disaster (I don't know how to put it together). I just need to call AJAX for three different arguments.
Thanks for any help
Well, there are various ways you can go about this.
One way is looping over your categories client side first, and make separate request per category. This is what you are essentially doing in your code. You are iterating over an array of categories and making a request for each.
Another way is to pass that array of categories to your handler. All you need to do is modify your handler to accept an array of integers or categories. Then you can return a JSON object. But this involves a lot more editing and on top of that it does not solve the issue of having different sizes and heights for each section.
Thus, below, I have modified the code a little bit to also keep track of multiple sections. There are just a few small edits we need:
Each section needs to have a category number, pagination number, content section, and a flag whether its loading or not. Each needs to be stored in a single list for tracking.
We need to iterate over each category to initialize it.
We need to iterate over each category on window scroll and check if the next item should be loaded
We need to make sure that each request relates to the requested category
Start by modifying your divs a little (this is just a matter of preference, i prefer storing metadata like this in an attribute instead of a class):
<div class="news_posts" data-category="6"></div>
<div class="news_posts" data-category="3"></div>
<div class="news_posts" data-category="2"></div>
Here's a modified JS (please be aware that I changed up some variable and function names):
jQuery(function($){
var $window = $(window);
var cats = [];
var contentDivs = $(".news_posts");
var initializeCats = function(){
// adds category objects to a list for tracking
for(var i = 0; i < contentDivs.length; i++){
var catNum = $(contentDivs[i]).attr("data-category");
var cat = {
catNum : catNum,
catPage : 1,
loading : true,
catDiv : $(contentDivs[i]);
};
cats.push(cat);
load_post(cat);
}
};
var load_post = function(cat) {
$.ajax({
type : "GET",
data : {
numPosts : 2,
pageNumber : cat.catPage,
cat : cat.catNum
},
dataType : "html",
url : "http://127.0.0.1:4001/wordpress/wp-content/themes/twentyeleven-child-theme/loopHandler.php",
beforeSend : function(){
if(page != 1){
// this was a bad idea when i wrote the article originally
// never concatenate strings on multiple lines by escaping
// the carriage return
// $content.append('<div id="temp_load" style="text-align:center">\
// <img src="/images/ajax-loader.gif" />\
// </div>');
cat.catDiv.append("<div class='temp_load' style='text-align:center'>" +
"<img src='/images/ajax-loader.gif' />" +
"</div>");
}
},
success : function(data){
$data = $(data);
if($data.length){
$data.hide();
cat.catDiv.append($data);
$data.fadeIn(500, function(){
cat.catDiv.find(".temp_load").remove();
cat.loading = false;
});
} else {
cat.catDiv.find(".temp_load").remove();
}
},
error : function(jqXHR, textStatus, errorThrown) {
cat.catDiv.find(".temp_load").remove();
alert(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
});
var onWindowScroll = function(){
for(var i = 0; i < cats.length; i++){
var cat = cats[i];
var contentDiv = cat.catDiv;
var content_offset = contentDiv.offset();
if( !cat.loading &&
($window.scrollTop() + $window.height()) >
(contentDiv.scrollTop() + contentDiv.outerHeight() + content_offset.top)
) {
cat.loading = true;
cat.catPage++;
load_post(cat);
}
}
}
initializeCats();
$window.scroll(onWindowScroll);
});
The PHP file is pretty much the same, just comment out the echo $numPosts line:
$numPosts = (isset($_GET['numPosts'])) ? $_GET['numPosts'] : 0;
$page = (isset($_GET['pageNumber'])) ? $_GET['pageNumber'] : 0;
$cat = (isset($_GET['cat'])) ? $_GET['cat'] : 0;
// echo $numPosts;
echo $page;
query_posts(array(
'posts_per_page' => $numPosts,
'paged' => $page,
'cat' => $cat
));
This is just something quick I whipped up. I HAVE NOT TESTED IT. Try it out, watch out for syntax errors, and cross your fingers :). I hope this will work for you and if it does not, we can look into modifying it so that it does.
I have a function that adds a new patient to the database, gets the json data back and then adds the new patient to the select menu. That works fine. I need to add that data into the corresponding text inputs i.e., input#patient_id, input#patient_firstname, etc. which should occur in the .ajax complete, but nothing happens.
Would appreciate any help!!
Ajax
$('#newpatient').click(function() {
var patientadd = $('#patientaddform').serializeArray();
$.ajax({
url: 'adam.php',
type: "POST",
data: patientadd,
dataType: 'json',
success: function(data){
var html = '';
var len = data.length;
for (var i = 0; i< len; i++) {
html += '<option selected="selected" value="' + data[i].patient_id + '">' + data[i].patient_firstname + ' ' + data[i].patient_lastname + ' : ' + data[i].patient_dob + '</option>';
}
alert(html);
$('#patientselect').prepend(html);
$('#patientselect').selectmenu('refresh', true);
},
complete: function (data) {
for(var id in data) {
$('input#' + id).val( data[id] );
}
}
});
});
json data returned
[{"patient_id":"22","patient_firstname":"","patient_lastname":"","patient_dob":"0000-00-00"}]
the corresponding text input fields are input#patient_id, input#patient_firstname, etc, that is why I'm trying to add the 'input#' to the id in the ajax complete and then add that val to the text input.
The params for the complete call back are jqXHR and textStatus. Not data. See http://api.jquery.com/jQuery.ajax/ for the correct definition of complete(jqXHR, textStatus)
Your json data is an array of objects, so you have to add take the first element of the array like this:
for(var id in data[0]) {
$('input#' + id).val( data[0][id] );
}
Or you have to adapt the server response.
Also consider #techfoobar's answer:
The params for the complete call back are jqXHR and textStatus. Not data. See http://api.jquery.com/jQuery.ajax/ for the correct definition of complete(jqXHR, textStatus)
I have the following situation: I need to make synchronized Ajax requests within a loop and display the returned result after each iteration in a div-element (appended on top with the previous results at the bottom). The response time of each request can be different but the order in which it should be displayed should be the same as issued. Here is an example with 3 requests. Lets say request "A" needs 3 seconds, "B" needs 1 second and "C" needs 5 seconds. The order I want to display the result is A, B, C as the requests were issued but the code I use shows the results in B, A, C.
Here is the code (JQuery Ajax request):
$(document).ready(function(){
var json = document.getElementById("hCategories").value;
var categories = eval( '(' + json + ')' );
for(curCat in categories) {
curCatKey = categories[curCat]['grKey'];
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) +
"&search=" + escape($("#hQuery").val()),
timeout: 8000,
async: false,
success: function(data) {
$("#content").append(data);
}
});
});
I thought it would work with "async:false" but then it waits until every Ajax call is finished and presents the results after the loop. I hope some of you can point out some different solutions, I am pretty much stuck.
Thanks in advance,
Cheers Chris
EDIT: Thanks for all the possible solutions, I will try these now one by one and come back with that one that fits my problem.
I have two solution proposals for this problem:
Populate generated divs
You could generate divs with ids in the loop and populate them when the request finishes:
$(document).ready(function() {
var json = document.getElementById("hCategories").value;
var categories = eval('(' + json + ')');
for (curCat in categories) {
(function(curCat) {
var curCatKey = categories[curCat]['grKey'];
$('#content').append('<div id="category-"' + escape(curCat) + '/>');
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) + "&search=" + escape($("#hQuery").val()),
success: function(data) {
$("#category-" + escape(curCat)).html(data);
}
});
})(curCat);
}
});
Or use a deferred
You can store jqXHR objects in an array and use a deferred to call the success functions in order, when all calls have finished.
$(document).ready(function() {
var json = document.getElementById("hCategories").value;
var categories = eval('(' + json + ')');
var requests;
for (curCat in categories) {
var curCatKey = categories[curCat]['grKey'];
requests.push($.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) + "&search=" + escape($("#hQuery").val())
}));
}
$.when.apply(requests).done(function() {
for (i in requests) {
requests[i].success(function(data) {
$("#content").append(data);
});
}
});
});
The first method has the advantage that it populates the containers continuously. I have not tested either of these function, but the logic should work the way I described it.
This would do the trick
var results = [];
var idx = 0;
for(curCat in categories) {
curCatKey = categories[curCat]['grKey'];
(function( i ) {
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) +
"&search=" + escape($("#hQuery").val()),
timeout: 8000,
async: false,
success: function(data) {
results[i] = data;
if (i == idx - 1) { // last one
for (var j=0; j < results.length; j++) {
$("#content").append(results[j]);
}
}
}
});
})(idx++);
I think something like this is what you're looking for. Might need some tweaking, I'm a little rusty on Deferred. Read up on it though, mighty powerful
deferred = $.Deferred()
for(curCat in categories) {
deferred.pipe(
function(resp){
postData = {} // set up your data...
return $.post("get_results.php", {data: postData, timeout: 8000})
.done(function(content){ $("#content").append(content) })
})
)
}
// Trigger the whole chain of requests
deferred.resolve()