Store items in array with using them later - javascript

I have code, which get json file from server and then render some if its elements on the page. In this code i also skip items with duplicate value of key "points". My question is, how do i make these skipped items to store somewhere, so if i click on item that has duplicate, it would link me to some other page with list of these duplicates?
Here is my code
var request = $.ajax({
type: "GET",
url: "example.com/rewards.json"
dataType: "json",
error: function (data, textStatus){
console.log( "it`s error" );
console.log( status );
console.log( data );},
success: function (data, textStatus){
console.log( "success" );
console.log( status );
console.log( data );
}
})
request.success(function(data, textStatus){
var lis = "";
var arr = [];
var iter = 0;
$.each(data.rewards, function(key, val){
if ($.inArray(val.points, arr) == -1)
{
lis += "<div class = 'ui-block-" + String.fromCharCode(97 + iter%3) + "'><a href ='#' class ='ui-link-inherit'>" + val.points + "</a></div>";
arr.push(val.points);
iter += 1;
}
});
$("#rewards_table").html(lis);
})
Description of what i want might be a little confusable, so feel free to ask me anything

You just do exactly that: Store them somewhere for use later.
For example, put this line at the top of your code:
var duplicates = [];
...and add this else to the if inside your $.each iterator function:
else
{
duplicates.push(val.points);
}
(I think I got your bracing style right there, a bit alien to me. :-) )
The above assumes all of your code is held in some kind of containing function, to avoid creating globals, and so duplicates (like your existing request variable) won't end up becoming a global.

Related

How to iterate through json arrays

I'm stuck in a script here, not sure how to get it to print in the div I set up. I imagine it's something related to how I'm handling the response.
The response in chrome devtools looks like this:
{
"[\"record one\", \"/description\"]": 0
}
I've attempted to use both each and map to iterate the data out but so far not going anywhere. I'm brand new to js and jquery, so the script is mostly from reading and examples.
Maybe some kind of nested loop? Here is my code -
$(function() {
return $('#myslider').slider({
range: true,
min: 0,
max: 20,
values: [1, 20],
stop: function(event, ui) {
var max, min;
min = ui.values[0];
max = ui.values[1];
$('#range').text(min + ' - ' + max);
$.ajax({
url: '/dir_scan',
type: 'get',
data: {
min: min,
max: max
},
dataType: 'json',
success: function(response) {
var albums;
albums = response;
$.each(albums, function(index, obj) {
var albumname, artist, li_tag;
li_tag = '';
albumname = obj.AlbumName;
artist = obj.Artist;
li_tag += '<li>Artist: ' + artist + ', Album: ' + albumname + '</li>';
$('#result').append($(li_tag));
return console.log;
});
}
});
}
});
});
As Will said in the comments, the JSON looks off.
But, you're on the right track of using .each, as it looks that you're returning an array of objects.
Here's an example of what to do:
var li_tag = '';
$.each(albums, function(index, obj) {
var albumname = obj.AlbumName;
var artist = obj.Artist
li_tag += '<li>Artist: ' + artist + ', Album: ' + albumname + '</li>';
$('#result').append($(li_tag));
return console.log;
});
Additionally, 'albums' should be set to the returned response of the success function. You're potentially creating a bunch of headache to try and decipher from the window.location; especially since the json example looks malformed. And, any work done with the data returned from the ajax call, should occur in the success function.
Here is how iteration worked for this situation. Comments in code -
success: function(response) {
var albums;
// side issue - but I had to clear the div to get a complete refresh
$('#result').empty();
albums = response;
$.each(albums, function(key, value) {
var albumname, li_tag, path;
li_tag = '';
// I found I had to do this parseJSON call otherwise
// I had no correct key/value pair, even though I had set dataType
// to JSON
albumname = jQuery.parseJSON(key);
path = albumname[1];
li_tag += '<li ><a href=/album' + encodeURI(albumname[1]) + '>' + albumname[0] + '</a href></li>';
$('#result').append($(li_tag));
return console.log;
});
Actually, value in the code is just the index number, but I had the actual key/value pair separated by commas, so again the parseJSON seemed to be the only way it would work. This, despite trying things like split and substr. Hope my answer is clear if not I can edit.

data[ ] in jsonp - what it means?

I am making an API request to Wikipedia, and everything seems to work but I can't figure out the meaning for the few lines of code, precisely
var articleTitles = data[1];
var articleUrls = data[3];
I have no idea what do index data[1] and data[3] mean and how do I figure out them on my own. This is from the Udacity tutorial but this was not clarified in detail, I only know it has something to do with the response...
var wikiUrl = 'https://en.wikipedia.org/w/api.php?action=opensearch&search=' + cityStr + '&format=json';
var wikiRequestTimeout = setTimeout(function () {
$wikiElem.text("Failed to get Wikipedia resources");
}, 5000);
$.ajax({
url: wikiUrl,
dataType: 'jsonp'
}).success(function(data) {
var articleTitles = data[1];
var articleUrls = data[3];
$.each(articleTitles, function(i, title) {
$wikiElem.append('<li>' + title + '</li>');
});
/* .error is not built into jsonp
*/
clearTimeout(wikiRequestTimeout); // clear timeout will stop timeout from happening
});
return false;
data is an object you can perceive it as an array (like) structure. It contains other arrays/objects inside of it, and to answer the question data[0] is the first of those child arrays and data[3] is the 4th one (it is a 0 based notation).
You can check this out - http://www.w3schools.com/json/json_syntax.asp

Ajax calls inside loop need sequential responses

I need to make 3 or less ajax calls, and the responses need to be appended to the dom in the same order they were requested.
I have the following function, but the problem is that the responses that I get are not necessarily in the correct order when they get appended to the dom.
I wouldn't want to use the async: false property because it blocks the UI and it's a performance hit of course.
mod.getArticles = function( ){
//mod.vars.ajaxCount could start at 0-2
for( var i = mod.vars.ajaxCount; i < 3; i++ ){
//mod.vars.pushIds is an array with the ids to be ajaxed in
var id = mod.vars.pushIds[i];
$.ajax({
url: '/ajax/article/' + id + '/',
type: "GET",
dataType: 'HTML',
error: function() {
console.error('get article ajax error');
}
}).done( function( data ) {
if (data.length) {
mod.appendArticle( data );
} else {
console.error('get article ajax output error');
}
});
}
};
You need to append the article to a certain position, based on for example the i variable you have. Or you could wait for all of the requests and then append them in order. Something like this:
mod.getArticles = function( ){
var load = function( id ) {
return $.ajax({
url: '/ajax/article/' + id + '/',
type: "GET",
dataType: 'HTML',
error: function() {
console.error('get article ajax error');
});
};
var onDone = function( data ) {
if (data.length) {
mod.appendArticle( data );
} else {
console.error('get article ajax output error');
}
};
var requests = [];
for( var i = mod.vars.ajaxCount; i < 3; i++ ){
requests.push(load(mod.vars.pushIds[i]));
}
$.when.apply(this, requests).done(function() {
var results = requests.length > 1 ? arguments : [arguments];
for( var i = 0; i < results.length; i++ ){
onDone(results[i][0]);
}
});
};
Here is an example using i to append them in the proper order when they all finish loading:
mod.getArticles = function( ){
// initialize an empty array of proper size
var articles = Array(3 - mod.vars.ajaxCount);
var completed = 0;
//mod.vars.ajaxCount could start at 0-2
for( var i = mod.vars.ajaxCount; i < 3; i++ ){
// prevent i from being 3 inside of done callback
(function (i){
//mod.vars.pushIds is an array with the ids to be ajaxed in
var id = mod.vars.pushIds[i];
$.ajax({
url: '/ajax/article/' + id + '/',
type: "GET",
dataType: 'HTML',
error: function() {
console.error('get article ajax error');
}
}).done( function( data ) {
completed++;
if (data.length) {
// store to array in proper index
articles[i - mod.vars.ajaxCount] = data;
} else {
console.error('get article ajax output error');
}
// if all are completed, push in proper order
if (completed == 3 - mod.vars.ajaxCount) {
// iterate through articles
for (var j = mod.vars.ajaxCount; j < 3; j++) {
// check if article loaded properly
if (articles[j - mod.vars.ajaxCount]) {
mod.appendArticle(articles[j - mod.vars.ajaxCount]);
}
}
}
});
}(i));
}
};
var success1 = $.ajax...
var success2 = $.ajax...
var success3 = $.ajax...
$.when(success1, success2, success3).apply(ans1, ans2, ans3) {
finalDOM = ans1[0]+ans2[0]+ans3[0];
}
Check this for more reference. This is still async, but it waits for all of them to complete. You know the order of invocation already, as its done through your code, so add the dom elements accordingly.
Solutions that rely solely on closures will work up to a point. They will consistently append the articles of a single mod.getArticles() call in the correct order. But consider a second call before the first is fully satisfied. Due to asynchronism of the process, the second call's set of articles could conceivably be appended before the first.
A better solution would guarantee that even a rapid fire sequence of mod.getArticles() calls would :
append each call's articles in the right order
append all sets of articles in the right order
One approach to this is, for each article :
synchronously append a container (a div) to the DOM and keep a reference to it
asynchronously populate the container with content when it arrives.
To achieve this, you will need to modify mod.appendArticle() to accept a second parameter - a reference to a container element.
mod.appendArticle = function(data, $container) {
...
};
For convenience, you may also choose to create a new method, mod.appendArticleContainer(), which creates a div, appends it to the DOM and returns a reference to it.
mod.appendArticleContainer = function() {
//put a container somewhere in the DOM, and return a reference to it.
return $("<div/>").appendTo("wherever");
};
Now, mod.getArticles() is still very simple :
mod.getArticles = function() {
//Here, .slice() returns a new array containing the required portion of `mod.vars.pushIds`.
//This allows `$.map()` to be used instead of a more cumbersome `for` loop.
var promises = $.map(mod.vars.pushIds.slice(mod.vars.ajaxCount, 3), function(id) {
var $container = mod.appendArticleContainer();//<<< synchronous creation of a container
return $.ajax({
url: '/ajax/article/' + id + '/',
type: "GET",
dataType: 'HTML'
}).then(function(data) {
if (data.length) {
mod.appendArticle(data, $container);//<<< asynchronous insertion of content
} else {
return $.Deferred().reject(new Error("get article ajax output error"));
}
}).then(null, function(e) {
$container.remove();//container will never be filled, so can be removed.
console.error(e);
return $.when(); // mark promise as "handled"
});
});
return $.when.apply(null, promises);
};
mod.getArticles() now returns a promise of completion to its caller, allowing further chaining if necessary.
Try utilizing items within mod.vars array as indexes; to set as id property of $.ajaxSettings , set returned data at this.id index within an array of responses. results array should be in same order as mod.vars values when all requests completed.
var mod = {
"vars": [0, 1, 2]
};
mod.getArticles = function () {
var results = [];
var ids = this.vars;
var request = function request(id) {
return $.ajax({
type: "GET",
url: "/ajax/article/" + id + "/",
// set `id` at `$.ajaxSettings` ,
// available at returned `jqxhr` object
id: id
})
.then(function (data, textStatus, jqxhr) {
// insert response `data` at `id` index within `results` array
console.log(data); // `data` returned unordered
// set `data` at `id` index within `results
results[this.id] = data;
return results[this.id]
}, function (jqxhr, textStatus, errorThrown) {
console.log("get article ajax error", errorThrown);
return jqxhr
});
};
return $.when.apply(this, $.map(ids, function (id) {
return request(id)
}))
.then(function () {
$.map(arguments, function (value, key) {
if (value.length) {
// append `value`:`data` returned by `$.ajax()`,
// in order set by `mod.vars` items:`id` item at `request`
mod.appendArticle(value);
} else {
console.error("get article ajax output error");
};
})
});
};
mod.getArticles();
jsfiddle http://jsfiddle.net/6j7vempp/2/
Instead of using a for loop. Call your function in response part of previous function.
//create a global variable
var counter = 0;
function yourFunc(){
mod.getArticles = function( ){
//mod.vars.ajaxCount could start at 0-2
//mod.vars.pushIds is an array with the ids to be ajaxed in
var id = mod.vars.pushIds[counter ];
$.ajax({
url: '/ajax/article/' + id + '/',
type: "GET",
dataType: 'HTML',
error: function() {
console.error('get article ajax error');
}
}).done( function( data ) {
if (data.length) {
mod.appendArticle( data );
} else {
console.error('get article ajax output error');
}
//increment & check your loop condition here, so that your responses will be appended in same order
counter++;
if (counter < 3)
{ yourFunc(); }
});
};
}
I'm faced same problem i'm solve this problem using following way.
just use async for get sequence wise response
<script type="text/javascript">
var ajax1 = $.ajax({
async: false,
url: 'url',
type: 'POST',
data: {'Data'},
})
.done(function(response) {
console.log(response);
});

Ajax request in for loop and order of indices

I have a problem concerning the execution of ajax requests in a for loop. I already searched the web for it and found some solutions which I already implemented to avoid running the request synchronously. Unfortunately these solutions don't provide information how to ensure, that the success block gets called in the correct order aswell.
This is my code:
for (var i = 0; i < array.length; i++) {
(function(index) {
var path = array[index].split(";")[1];
var selectedRevision = array[index].split(";")[0];
$.ajax({
url: 'svntojson.jsp?revHistoryForPath=' + path,
dataType:'text',
success:function(data){
console.log(index);
var $li = $("<li/>").text(path).addClass("ui-corner-all")
.prepend("<div class='handle'><span class='ui-icon ui-icon-carat-2-n-s'></span></div>")
.append('<button class="delete"></button>')
.append('<select class="revHistoryOptions" style="float:right;margin-right:5px;">' + data.trim() + '</select>');
$("#list").append($li);
$("#list").sortable('refresh');
$('.revHistoryOptions').eq(index).children('option[value=' + selectedRevision + ']').attr('selected', 'selected');
}
});
})(i);
}
However the order of indices can change because the one ajax request succeeds earlier. This wouldn't be a problem but I am appending some list elements in the success block and I need the exact order.
So my question is how to ensure that the success block of my ajax request will be called in the order of the for loop indices from 0 to n-1.
WRONG DESIGN : If you want a complete synchronized behavior and not involving any user interaction between iterations, you can avoid
looping and use single ajax request.
You can use a single ajax when you want it completely synchronized:
$.ajax({
url: 'svntojson.jsp?inputArray=' + array,
dataType: 'json',//Note I changed this to json to receive the array on outputs
success: function (data) {
var resArray = data;
for (var index = 0; index < resArray.length; index++) {
var res = resArray[index];
var $li = $("<li/>").text(res.path).addClass("ui-corner-all")
.prepend("<div class='handle'><span class='ui-icon ui-icon-carat-2-n-s'></span></div>")
.append('<button class="delete"></button>')
.append('<select class="revHistoryOptions" style="float:right;margin-right:5px;">' + res.data + '</select>');
$("#list").append($li);
$("#list").sortable('refresh');
$('.revHistoryOptions').eq(index).children('option[value=' + res.selectedRevision + ']').attr('selected', 'selected');
}
}
});
on the server:
process the input array and generate output for each element of array. (Psuedocode as following):
var resArray = new Array(inputArr.length);
for (var i = 0; i < inputArr.length; i++) {
var res = new res();
res.path = inputArr[i].split(";")[1];
res.selectedRevision = inputArr[i].split(";")[0];
resArray.push(res);
}
return resArray;

Skip duplicate items while rendering page from json

I'm rendering page using ajax and json. Structure of my json is {"status":"ok","rewards":[{"id":201,"points":500},{"id":202,"points":500}]
How do i make ajax loading data only once one if 'points' duplicates in any of hashes?
E.g. i have json with few hashes in which 'points' have same value
Here is my code
$("#page").live('pagecreate', function(e) {
var request = $.ajax({
type: "GET",
url: "example.com/file.json",
dataType: "json",
error: function (data, tex
tStatus){
console.log( status );
console.log( data );},
success: function (data, textStatus){
console.log( "success" );
console.log( status );
console.log( data );
}
})
request.success(function(data, textStatus){
var lis = "";
var seen = {};
$.each(data.rewards, function(key, val){
lis += "<div class = 'reward-ui ui-block-" + String.fromCharCode(97 + key%3) + "'><a href ='#' class ='ui-link-inherit'>" + val.points + "</a></div>";
});
$(".ui-grid-b").html(lis);
});
//$('.even-odd').listview('refresh');
})
});
Add a local array which will store all the items used. Push into this array in $.each function and before doing lis += " " check if the value already exists in the temp array.
Other than that you could try server side sorting before retrieving data ... like suggested above.

Categories