I have a strange problem with my script. I am getting a JSON result set and want to iterate it and then display in a div. I checked fiddler and I can see the entire set being returned like the set below
[{"EPubID":71,"SerialID":1,"PartnerID":343,"Partner":"Aberdeen, City of ","PublicationTitle":"Uploading multiple files test","AuthFirstName":null,"AuthMiddleName":null,"AuthLastName":null,"AuthFullName":null,"PublicationYear":2011,"SubmitterEmail":null,"VolumeNumber":null,"Issue":null,"AlreadyInCatalog":false,"InCatalog":"No","Status":"D","Notes":"testing multiple file uploads","IsMonograph":false,"Monographed":"No","SubmittedDate":"\/Date(1317913458810)\/","SubmittedBy":"admin","ApprovedDate":"\/Date(1317914842263)\/","ApprovedBy":"admin","SubmittingPartnerID":0,"OriginalRefId":"343-71","SerialName":"None","URL":null,"InfoRecordID":0,"LastModified":"\/Date(-62135568000000)\/","IsSerial":false,"Approved":false,"Delete":false,"Pending":false,"files":null},{"EPubID":72,"SerialID":19,"PartnerID":26,"Partner":"Digital Archives","PublicationTitle":"testing multiple file uploads ","AuthFirstName":null,"AuthMiddleName":null,"AuthLastName":null,"AuthFullName":null,"PublicationYear":2001,"SubmitterEmail":null,"VolumeNumber":"1","Issue":"1","AlreadyInCatalog":false,"InCatalog":"No","Status":"A","Notes":"this should work","IsMonograph":false,"Monographed":"No","SubmittedDate":"\/Date(1317915134767)\/","SubmittedBy":"admin","ApprovedDate":"\/Date(1317915430627)\/","ApprovedBy":"admin","SubmittingPartnerID":0,"OriginalRefId":"26-72","SerialName":"Fake Test Serial","URL":null,"InfoRecordID":0,"LastModified":"\/Date(-62135568000000)\/","IsSerial":false,"Approved":false,"Delete":false,"Pending":false,"files":null}]
The problem is my script is only displaying the first item returned and nothing else. Here is my script.
function SearchExistingEpubs() {
var title = $("input#PublicationTitle").val();
$('#Results').hide();
$("div#SearchResults").innerHTML = '';
$.getJSON('/EPub/SearchExistingEpubs/' + title, null, function (data) {
var items = [];
var found = false;
$.each(data, function (key, val) {
found = true;
$("div#SearchResults").empty();
$("div#SearchResults").append("Title: " + val.PublicationTitle + " Owning Partner: " + val.Partner + " Year: " + val.PublicationYear) ;
$('#Results').show();
});
if (!found) {
$("div#SearchResults").empty();
//$("div#SearchResults").html('');
$("div#SearchResults").append("No documents found");
$('#Results').show();
//$('#Results').slideUp(10000);
$('#Results').animate({height:'toggle'},10000);
//$('#Results').fadeOut(10000);
}
//$('#Results').show();
});
};
You're wiping out the contents of the div in each iteration of the loop with your call to empty():
$.each(data, function (key, val) {
found = true;
$("div#SearchResults").empty(); // <------ REMOVE this line
$("div#SearchResults").append("Title: " + val.PublicationTitle + " Owning Partner: " + val.Partner + " Year: " + val.PublicationYear) ;
$('#Results').show();
});
But doing dom updates in a loop is not usually a good idea. Why not build up your string and do one dom update:
var content = '';
$.each(data, function (key, val) {
found = true;
content += "Title: " + val.PublicationTitle + " Owning Partner: " + val.Partner + " Year: " + val.PublicationYear;
});
$("div#SearchResults").append(content);
$('#Results').show();
In your .each loop you're calling $("div#SearchResults").empty(); this will clear any content you've previously appended to this div.
Try the following:
function SearchExistingEpubs() {
var title = $("input#PublicationTitle").val();
$('#Results').hide();
$("div#SearchResults").empty();
$.getJSON('/EPub/SearchExistingEpubs/' + title, null, function (data) {
$("div#SearchResults").empty();
var items = [];
if (data.length) {
$.each(data, function (key, val) {
$("div#SearchResults").append("Title: " + val.PublicationTitle + " Owning Partner: " + val.Partner + " Year: " + val.PublicationYear);
});
$('#Results').show();
} else {
$("div#SearchResults").append("No documents found");
$('#Results').show();
$('#Results').animate({height:'toggle'},10000);
}
});
};
Related
I get the German text of a specific keyword (var title) and output it as html afterwards. This is working fine, but now I wanted to load the English text if the German text isn't available. This is also working fine with my code:
var length = 500;
var title = $('#title').attr('data-title');
var lang = 'de';
var url = 'https://' + lang + '.wikipedia.org/w/api.php?format=json&action=query' +
'&prop=extracts&exintro=&explaintext=&titles=' + title + '&redirects=0';
$.getJSON("http://query.yahooapis.com/v1/public/yql",
{
q: "select * from json where url=\"" + url + "\"",
format: "json"
},
function (data) {
$.each(data.query.results.json.query.pages, function (key, val) {
var text = val['extract'];
console.log('lang-' + lang + '-text: ' + text);
if (text) {
text = text.replace('Siehe auch:', '');
} else if (!text && lang != 'en') {
var url = 'https://en.wikipedia.org/w/api.php?format=json&action=query' +
'&prop=extracts&exintro=&explaintext=&titles=' + title + '&redirects=0';
$.getJSON("http://query.yahooapis.com/v1/public/yql",
{
q: "select * from json where url=\"" + url + "\"",
format: "json"
},
function (data) {
$.each(data.query.results.json.query.pages, function (key, val) {
text = val['extract'];
console.log('lang-en-text: ' + text);
});
});
}
console.log('lang-end-text: ' + text);
if (text) {
text = text.length > length ? text.substring(0, length - 3) + '...' : text;
$('#text').html(text);
} else {
setTimeout(function () {
$('#text').html('<?= __('EMPTY'); ?>');
}, 1000);
}
console.log(data);
});
});
But after the second $.getJSON is closed, text is empty again. That means that
console.log('lang-en-text: ' + text);
is working and outputs the correct English text in the console, but after closing the $.getJSON the variable text has no value anymore, what I can confirm with the output in the console:
console.log('lang-end-text: ' + text);
How can I keep the value? Also is there a better way to check if the specific content I want to get (the text in this case) is available BEFORE, so I don't have to make two $.getJSON requests? Or is my way the right way to do it?
EDIT: It's working now!
I found the solution thanks to moopet and used .done and a new function called .setText to set the text. Maybe this helps others too as the question seems to get upvoted a lot. This is my code now:
var length = 500;
var title = $('#title').attr('data-title');
var lang = 'de';
var url = 'https://' + lang + '.wikipedia.org/w/api.php?format=json&action=query' +
'&prop=extracts&exintro=&explaintext=&titles=' + title + '&redirects=0';
$.getJSON("http://query.yahooapis.com/v1/public/yql",
{
q: "select * from json where url=\"" + url + "\"",
format: "json"
},
function (data) {
$.each(data.query.results.json.query.pages, function (key, val) {
var text = val['extract'];
console.log('lang-' + lang + '-text: ' + text);
if (text) {
text = text.replace('Siehe auch:', '');
} else if (!text && lang != 'en') {
var url = 'https://en.wikipedia.org/w/api.php?format=json&action=query' +
'&prop=extracts&exintro=&explaintext=&titles=' + title + '&redirects=0';
$.getJSON("http://query.yahooapis.com/v1/public/yql",
{
q: "select * from json where url=\"" + url + "\"",
format: "json"
},
function (data) {
$.each(data.query.results.json.query.pages, function (key, val) {
text = val['extract'];
console.log('lang-en-text: ' + text);
});
}).done(function() {
setText(text);
});
}
console.log(data);
});
}).done(function() {
setText(text);
});
function setText(text) {
if (text) {
text = text.length > length ? text.substring(0, length - 3) + '...' : text;
$('#text').html(text);
} else {
$('#text').html('Text not available.');
}
}
You're running afoul of asynchronous javascript calls.
Your success callback:
function (data) {
$.each(data.query.results.json.query.pages, function (key, val) {
text = val['extract'];
console.log('lang-en-text: ' + text);
});
});
is called asynchronously. In other words, it's deferred until the HTTP request has finished.
Your
console.log('lang-end-text: ' + text);
is called immediately, before text is assigned, because that's how execution progresses. If you put the code for things you want to do with the text inside the callback function, you'll get the results you want.
I'm trying to build a new project.
It's going to be a tradebot for a website, now to store my received items into my database i whould like some info send with each item (being the name , asseid , tradeid,...).
The following code works.
offers.on('receivedOfferChanged', function (offer, oldState) {
logger.info(offer.partner.getSteam3RenderedID() + " Offer #" + offer.id + " changed: " + TradeOfferManager.getStateName(oldState) + " -> " + TradeOfferManager.getStateName(offer.state));
// Alert us when we accept an offer
if (offer.state == TradeOfferManager.ETradeOfferState.Accepted) {
offer.getReceivedItems(function (err, items) {
if (err) {
logger.error("Couldn't get received items: " + err);
} else {
var names = items.map(function(item) {
return item.name;
});
var assetids = items.map(function(item) {
return item.assetid;
});
// Log a comma-separated list of items received
logger.info("Received: " + names + " " + assetids.join(', '));
}
});
}
});`
But the thing is, is there any way to shorten the following code :
var names = items.map(function(item) {
return item.name;
});
var assetids = items.map(function(item) {
return item.assetid;
});
So it gets the item name , assetid, ... out of the array and stores them in sperate variables ?
You can use push() method to add values into both arrays in a single loop. Try:
var names = [],
assetids = [];
items.forEach(function(item) {
assetids.push(item.assetid);
names.push(item.name);
});
I have multiple items in my JSON list. I want to loop through it and display it on my page. I can't seem to get to the next object though.
{
"room":[
{"campusName":"A",
"buildingCode":"B",
"roomNumber":"208",
"times":["7-8", "9-10"]
}],
"room2":[
{"campusName":"C",
"buildingCode":"D",
"roomNumber":"208",
"times":["7-8", "9-10"
]}
]}
$(document).ready(function(){
$.getJSON("data.json", function(data){
$.each(data.room, function(){
for(var i = 0; i < data.length; i++){
$("ul").append("<li>campus: "+this['campusName']+"</li><li>building: "+this['buildingCode']+"</li><li>times: "+this.times+"</li>");
}
});
});
});
Try this
var list = '';
$.each(data, function (i, root) {
$.each(root, function (i, el) {
list += "<li>campus: " + this.campusName + "</li><li>building: " + this.buildingCode + "</li><li>times: " + this.times.join(' ') + "</li>";
});
});
$('ul').html(list);
Example
If root's has only one element in array
var list = '';
$.each(data, function (i, root) {
list += "<li>campus: " + root[0].campusName + "</li><li>building: " + root[0].buildingCode + "</li><li>times: " + root[0].times.join(' ') + "</li>";
});
$('ul').html(list);
Example
$.each(data, ..) --> Each element will be:
"room":[
{"campusName":"A",
"buildingCode":"B",
"roomNumber":"208",
"times":["7-8", "9-10"]
}]
Then, this[0] will provide the object you need to construct your li:
$.each(data, function(){
$("ul").append("<li>campus: "+this[0]['campusName']+"</li><li>building: "+this[0]['buildingCode']+"</li><li>times: "+this[0].times+"</li>");
});
Fiddle
The below code successfully runs a query and returns the results. However when being displayed on the page, the label for
item.username and item.imageURL
are returning as undefined or in the images case "not found).
I believe I may have to change the code which is displaying this on the page, because a recent query change is now returning multiple possibilities for username:
Before it just returned fromUser for this, now the query also can potentially return toUser. However the resulsts on the page should only show one or the other, not both.
Just stuck on what I need to adjust below to allow this?
var currentUser = Parse.User.current();
var FriendRequest = Parse.Object.extend("FriendRequest");
var queryOne = new Parse.Query(FriendRequest);
queryOne.include('fromUser');
queryOne.include("myBadge");
queryOne.equalTo("fromUser", currentUser);
var queryTwo = new Parse.Query(FriendRequest);
queryTwo.include('toUser');
queryTwo.include("myBadge");
queryTwo.equalTo("toUser", currentUser);
var mainQuery = Parse.Query.or(queryOne, queryTwo);
mainQuery.equalTo("status", "Connected");
mainQuery.find({
success: function(results) {
var friends = [];
for (var i = 0; i < results.length; i++) {
friends.push({
imageURL: results[i].get('fromUser').get('pic'),
username: results[i].get('fromUser').get('username'),
userId: results[i].get('fromUser').id,
status: results[i].get('status'),
// Saves the object so that it can be used below to change the status//
fetchedObject: results[i]
});
}
var select = document.getElementById("FriendsConnected");
$.each(friends, function(i, v) {
var opt = v.username;
var el = document.createElement("option");
el.textContent = opt;
el.value = opt;
select.appendChild(el);
})
$('#containerFriends').empty();
$('#containerFriendsConnected').empty();
_.each(friends, function(item) {
var wrapper = $('<div class="portfolio-item-thumb one-third"></div>');
wrapper.append('<img class="responsive-image friendImgOutline" src="' + item.imageURL + '" />'+ '<br>');
wrapper.append('<div class="tag">' + item.username + '</div>');
wrapper.append('<div type="button" class="btn btn-danger mrs decline">' + 'Unfriend' + '</div>');
$('#containerFriends').append(wrapper);
//The following lets the user accept or decline a friend request by changing the status the status from Pending to Declined/////
$(document).on('click', function() {
$(".decline").click(function() {
item.fetchedObject.set("status", "Rejected");
item.fetchedObject.save(null, {
success: function(results) {
console.log("REJECTED");
},
error: function(contact, error) {
// The save failed.
// error is a Parse.Error with an error code and description.
alert("Error: " + error.code + " " + error.message);
}
});
});
});
});
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
The mainQuery needs to include the keys as well.
var mainQuery = Parse.Query.or(queryOne, queryTwo);
mainQuery.include("toUser"); //Add this line
mainQuery.include("fromUser"); //Add this line
mainQuery.equalTo("status", "Connected");
I'm trying to use typeahead's matcher function to check if my search returns no results. If it returns no results i want to append a div on the end of the search bar. However the matcher function is causing my highlighter to break and return random results. Does anyone know if there is a way to accomplish this without using the matcher function or how use it properly in this instance? I think i might be taking the wrong approach.
$('.shop_search').typeahead({
source: function (query, process) {
map = {};
$.each(data, function (i, data) {
map[data.text] = {
address: data.text2,
name: data.text,
post: data.post
};
shops.push(data.text);
});
process(shops);
shops = [];
},
minLength: 3,
matcher: function (item) {
if (item.indexOf(this.query) == -1) {
$(".dropdown-menu").append($('<li><button class="btn" >Advanced Search</button></li>'));
return true;
}
},
highlighter: function (item) {
var p = map[item];
var itm = ''
+ "<div class='typeahead_primary'>" + p.name + "</div>"
+ "<div class='typeahead_secondary'>" + p.address + </div>"
+ "</div>"
+ "</div>";
return itm;
},
});
Seems to me that you forgot a "
+ "<div class='typeahead_secondary'>" + p.address + </div>"
should be
+ "<div class='typeahead_secondary'>" + p.address + "</div>"