How can I get specific data from JSON? - javascript

How can I get specific data from JSON?
JSON:
[
{ "TotalPageCount": 66 },
{ "TotalTitleCount": 199 },
{ "Title": "cola" },
{ "Title": "elvis tom" },
{ "Title": "dvd" }
]
Javascript Code:
<script>
function updateTitlesArea() {
$.getJSON(
"/lates/json/",
null,
function(data) {
$("#titlesDiv").html("");
$("#pagesDiv").html("");
var x;
if (data.length > 0) {
for (x in data) {
$("#titlesDiv").html($("#titlesDiv").html() +
"<li>" + data[x].Title + "" +
"</li>"
);
}
} else {
$("#titlesDiv").html("<li>no entry</li>");
}
});
}
</script>
I'm trying to get {"TotalPageCount":66} AND {"TotalTitleCount":199}
from Javascript. Please provide me a method to get them?
Thanks a lot.
Update
Something going wrong, I tried all solutions but not worked fine.
I have control on json format:
Current Json Builder:
if (title.Any())
{
foreach (var x in title)
{
result.AddLast(new { Title = x.Title });
}
}
result.AddLast(new { TotalPageCount = totalPageCount });
result.AddLast(new { TotalTitleCount = totalTitleCount });
return Json(result.ToList(), JsonRequestBehavior.AllowGet);
I made a small change in json format, took totalpage and title count to end of json.
Current:
[{"Title":"kola"},{"Title":"yilmaz
ozdil"},{"Title":"dvd"},{"Title":"truly madly
deeply"},{"Title":"deportivo de la coruna"},{"Title":"sizi seven
kisiyle sevdiginiz kisinin farkli olmasi"},{"Title":"kadinlarin bavul
gibi canta tasimalari"},{"Title":"hosbuldum"},{"Title":"sark
cibani"},{"Title":"mevsimler gecerken"},{"Title":"bir kerede kolon
gibi sicmak"},{"Title":"gelismek"},{"Title":"faz ve alasim
bilimi"},{"Title":"memetq"},{"Title":"ogrencilerin sinav kagidina
dustugu ilginc notlar"},{"Title":"cami duvarina
isemek"},{"Title":"kufurden sonra tovbe etmek"},{"Title":"gida tarim
ve hayvancilik bakanligi"},{"Title":"cevre orman ve sehircilik
bakanligi"},{"Title":"google da nikah masasi
calmak"},{"TotalPageCount":9},{"TotalTitleCount":199}]
With my code and given examples I still couldn't get the TotalPageCount and TotalTitleCount.
For the record: Maybe next time I can add more attributes next to Title.
So I would like to keep that json format.
Thanks for advance

When you do x in data you get every key of objects. So you have to do a simple check if it's TotalPageCount or TotalTitleCount. Like this;
<script>
function updateTitlesArea() {
$.getJSON(
"/lates/json/",
null,
function(data) {
var x, totalPageCount, totalTitleCount;
$("#titlesDiv").html("");
$("#pagesDiv").html("");
if (data.length > 0) {
for (x in data) {
if('TotalPageCount' == x) {
totalPageCount = data[x];
continue;
}
if('TotalTitleCount' == x) {
totalTitleCount = data[x];
continue;
}
$("#titlesDiv").html($("#titlesDiv").html() +
"<li>" + data[x].Title + "" +
"</li>"
);
}
// You can do here whatever you want with 'totalPageCount' and 'totalTitleCount'
} else {
$("#titlesDiv").html("<li>no entry</li>");
}
});
}
</script>

It's an array, so
if (data.length > 0) {
var obj = data[0]; // array, not object
for (key in obj) {
$("#titlesDiv").html(
$("#titlesDiv").html() +
"<li><a href=\"/" + obj[key].Title.replace(/ /g, '-') + "\">" +
obj[key].Title + "</a>" +
"</li>"
);
}

Are you using jQuery right? You can try something like this:
var prom = $.getJSON('/lates/json/'),
ar;
prom.then(function (data) { ar = data; });
After that, you will have the response array in ar. You will be able to access to your required values in this fashion:
ar[0].TotalPageCount
ar[1].TotalTitleCount
I hope this will help you. Good luck.

With your current JSON format, it'd be something like this. It'd be better if you could change the JSON format, though.
<script>
function updateTitlesArea() {
$.getJSON(
"/lates/json/",
null,
function(data) {
$("#titlesDiv").html('<ul></ul>'); // <li> goes inside <ul> or <ol>
$("#pagesDiv").empty();
var has_titles = false;
for(var i = 0; i < data.length; i++) {
if("Title" in data[i]) {
$("#titlesDiv ul").append(
'<li>' + data[i].Title + "" +
"</li>"
);
has_titles = true;
}
}
if( !has_titles ) {
$("#titlesDiv ul").html("<li>no entry</li>");
}
}
);
}
</script>

Related

class recovery problem generated by do while loop by event

I would like to retrieve the class when I click on the link that contains -> class="prez_col-'+i +'" in the viewPoster function. I don't know if it's because of the html() function or the event that prevents me from retrieving the name of the class from the DOM when I click on
template += '<p class="prez_title">' + data[i].title + '</p><img src="' + condJaq + '" class="prez_jaquette" />';
$("#prez_choiseJaq").html(template);
I tried to put onclick in the template variable:
template += '<p class="prez_title">' + data[i].title + '</p><img src="' + condJaq + '" class="prez_jaquette" />';
$("#prez_choiseJaq").html(template);
I have an error! when on one of the posters displays
File HTML
<div id="prez_rech" class="prez_rech">
<label for="fname">Recherche du film :</label>
<input type="text" placeholder="Entrez votre film ici" id="prez_input">
<xf:button type="button" id="prez_btn">Rechercher</xf:button>
</div>
<div id="prez_choiseJaq"></div>
<footer class="prez_footer">Created by Marilyn</footer>
<script type="module" src="js/vendor/prez/prez.js"></script>
File getValue .js
import { array } from './params.js';
const key = array['key'];
const urlMovie = array['urlMovie'];
const noCover = array['noCover'];
const urlImg = array['urlImg'];
const urlJaq = array['urlJaq'];
var jaq = document.getElementById("prez_choiseJaq");
var input = document.getElementById("prez_input");
var myBtn = document.getElementById("prez_btn");
var rech = document.getElementById("prez_rech");
var jaqSelected = $("a.prez_col-" + i);
var data = [];
var inputRep;
var urlNoCover = urlImg + noCover;
var url = urlMovie + key;
var i;
var test = false;
input.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
event.preventDefault();
inputRep = input.value;
getValue();
}
});
myBtn.addEventListener("click", event => {
event.preventDefault();
inputRep = input.value;
getValue();
});
jaqSelected.click(function() {
alert(jaqSelected);
});
async function getValue() {
console.log(inputRep);
try {
const response = await fetch(url + "&language=fr-FR&query=" + inputRep + "&page=1&include_adult=false");
const responseData = await response.json();
data = responseData?.results;
console.log(data);
if (!data.length) {
alert("Le film que vous demandez n'est pas disponible !");
} else {
viewPoster();
}
} catch (error) {
console.log(error);
}
return data;
};
function viewPoster() {
test = false;
if (data) {
var template = "";
jaq.style.display = "inline-grid";
i = -1;
do {
i += 1;
console.log(i);
let condJaq;
if (data[i].poster_path == null) {
condJaq = urlNoCover;
} else {
condJaq = urlJaq + data[i].poster_path;
};
template += '<p class="prez_title">' + data[i].title + '</p><img src="' + condJaq + '" class="prez_jaquette" />';
$("#prez_choiseJaq").html(template);
} while (i < data.length);
};
};
function selected(arg) {
console.log(arg);
};
export { getValue };
File params.js
var array = {
key: "exemple",
urlMovie: 'https://api.themoviedb.org/3/search/movie?api_key=',
urlSerie: 'https://api.themoviedb.org/3/search/tv?api_key=',
urlImg: 'styles/prez/img/',
urlJaq: "https://image.tmdb.org/t/p/w154",
noCover: "no_cover.jpeg",
};
export { array };
File prez.js
import { array } from './params.js';
import { getValue } from './getValue.js';
do you have an idea ?
Thanks in advance.
There are so many issues here it's difficult to explain why your code isn't working. The issue with the for loop is a candidate for the error you didn't share, but there others.
The primary problem is that you were not adding a click handler for your links.
I've converted your code from module based JS (because I believe that's difficult to do in a snippet), mocked the Movie API call and cleaned up the code to remove most unnecessary globals, leverage jQuery more, and fix the for loop.
var array = {
key: "exemple",
urlMovie: 'https://api.themoviedb.org/3/search/movie?api_key=',
urlSerie: 'https://api.themoviedb.org/3/search/tv?api_key=',
urlImg: 'styles/prez/img/',
urlJaq: "https://image.tmdb.org/t/p/w154",
noCover: "no_cover.jpeg",
};
function mock_fetch(url, rep) {
const query = url + "&language=fr-FR&query=" + rep + "&page=1&include_adult=false"
// response = await fetch(query);
// return await reponse.json()
return { results: [{ poster_path: "This is the poster path"
, title: rep
}
,{ poster_path: "Some other path"
, title: "Some other movie"
}
]
}
}
var data; // this will hold whatever data retrieved by the last query to the movie API (may be null/undefined)
async function getValue(inputRep) {
try {
const responseData = mock_fetch(array.urlMovie + array.key, inputRep);
data = responseData?.results;
if (!data.length) {
alert("Le film que vous demandez n'est pas disponible !");
} else {
viewPoster(data);
}
} catch (error) {
console.error(error);
}
return data;
};
function viewPoster() {
$("#prez_choiseJaq").css("display", "inline-grid");
var template = "";
data.forEach( (film, index) => {
template += `${film.title}</p><img src="${film.poster_path?(array.urlJaq + film.poster_path):array.urlImg+array.noCover}" class="prez_jaquette" />`;
})
$("#prez_choiseJaq").html(template);
};
function selectMovie(event) {
event.preventDefault();
getValue($('#prez_input').val());
}
function doSomethingWithFilm(event) {
let index = $(this).data('index');
console.log(`The index you clicked was ${index}`)
if (data && data[index]) {
console.log(`The data for that index is ${JSON.stringify(data[index])}`)
} else {
console.log(`The data for that index is not available`)
}
}
function init() {
$('#prez_input').keypress(event => { event.key === "Enter" && selectMovie(event) });
$('#prez_btn').on("click", selectMovie);
// Add the click handler for the links as a delegate because the links do not exist at the time this code is executed
$(document).on("click", ".prez_col", doSomethingWithFilm);
}
$(init)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</script>
</head>
<body>
<div id="prez_rech" class="prez_rech">
<label for="fname">Recherche du film :</label>
<input type="text" placeholder="Entrez votre film ici" id="prez_input">
<xf:button type="button" id="prez_btn">Rechercher</xf:button>
</div>
<div id="prez_choiseJaq"></div>
</body>
</html>
Your do {} while () loop condition is trying to loop one beyond your data array. The problem is how you set up and increment your iterator variable: i.
You set your iterator to i = -1; before the loop, then, first thing in the loop you increment it: i += 1;, and the while condition is set to stop looping when i is equal to the array length: while ( i < data.length ). If an array has one element, i must be value 1 to discontinue the loop. At the end of the first pass i is equal to 0. Even in the case of a single array element it is still less than the length of the array so the loop will loop again. One element, two loops. Two elements, three loops. Three elements, four loops, etc.
The easy fix is change:
while (i < data.length);
...to:
while (i < data.length - 1);
let data = ['a','b','c','d','e'];
// ALWAYS ONE TO MANY LOOPS
let i = -1;
do {
i += 1;
console.log(i, data[i]);
} while (i < data.length);
// EASY FIX
i = -1;
do {
i += 1;
console.log(i, data[i]);
} while (i < data.length - 1); // <-- reduce length by one
// BETTER YET
i = 0;
do {
console.log(i, data[i]);
i += 1; // <-- move iterator increment to end of loop
} while (i < data.length);
How to use an iterator variable to control a loop:
Regardless of what type of loop you use: for, while, do while, it makes more sense to me to use your loop iterator, when you need one, as such:
let data = [1,2,3,4,5,6];
let ii = 0;
do {
console.log(ii, data[ii]);
ii++;
} while ( ii < data.length );
Before the loop, set ii to 0. The loop starts, use ii as 0, then at the very end of the loop increment ii. Every element is accessed, and only accessed once.
Here's the function (simple fixed) where you're do {} while () loop is:
function viewPoster() {
test = false;
if (data) {
var template = "";
jaq.style.display = "inline-grid";
i = -1;
do {
i += 1;
console.log(i);
let condJaq;
if (data[i].poster_path == null) {
condJaq = urlNoCover;
} else {
condJaq = urlJaq + data[i].poster_path;
};
template += '<p class="prez_title">' + data[i].title + '</p><img src="' + condJaq + '" class="prez_jaquette" />';
$("#prez_choiseJaq").html(template);
} while (i < data.length - 1);
};
};

Need JavaScript example for fetch() etc

I want to learn such new JavaScript features as fetch() and arrow functions. To this end, I selected a function from a recent app, and attempted to replace older features with new. Very little success. Here's my original function:
function popNames(arNumbers,ctrlName) {
var arSortedList = [];
var strNameList = "";
$.getJSON("NAME.json").done(function(zdata) {
$.each(arNumbers, function(i, ydata) {
$.each(zdata.NAME, function(k,v) {
if(v.idName == ydata) {// important: === did NOT work
if(ctrlName) arSortedList.push(v.last + ", " + v.first + ";" + v.idName);
else arSortedList.push(v.last + ", " + v.first);
}
}); // each element of NAME.json
}); // each idName value in the array passed
if(ctrlName) {
setOptions(arSortedList, ctrlName);
} else {
strNameList = arSortedList.join();
}
}); // getJSON NAME
}
I was successful using this line:
fetch("NAME.json").then(zdata => zdata.json())
but nothing I did after that worked. I'd appreciate seeing an example from which I can learn.
function popNames(arNumbers,ctrlName) {
let arSortedList = [];
let strNameList = "";
fetch("NAME.json").then(zdata => zdata.json())
.then(zdata => {
for(const ydata of arNumbers) {
for(const v of zdata.NAME) {
if(v.idName == ydata) { // important: === did NOT work
if(ctrlName) arSortedList.push(v.last + ", " + v.first + ";" + v.idName);
else arSortedList.push(v.last + ", " + v.first);
}
}
}
if(ctrlName) {
setOptions(arSortedList, ctrlName);
} else {
strNameList = arSortedList.join();
}
}); // getJSON NAME
}
I was researching why I couldn't next two Array.forEach statements, and discovered a new iterable construction (for...of).

Setting an empty array index

i have an array that holds student answers for given questions.
if a student gives an answer, it gets inserted into the array at the current index like answers[questionindex] = answer
later, i can read the array and map the entries to the given question-array
this case:
[
"answer",
undefined, // student has not given answer
"answer2",
]
works. (looping over the array, simply outputting "no answer given" if (answers[questionindex] === undefined)
but it doesn't work when the LAST answers were undefined (1 or more)
they just don't exist (of course).
how can i set those fields to undefined (like, after a timer reaches zero), to show that there was no answer given?
right now, the average-calculation shows 100% correct for 3 given (correctly), then 2 not given at all
code
var testResults = {
addRoom: function(Id, teacher) { // room pseudoconstructor
this[Id] = {
created: moment(),
runningProblem: false,
time: 0, // holds the countdown for the current problem
getTime: function() { // returns the countdown-counter
return this.time;
},
Id: Id,
teacher: teacher,
getCurrentSolution: function() {
return math.eval(this.testProblems[this.getCurrentProblemIndex()].problem);
},
getTimeTaken: function() {
return this.getCurrentProblemTimeLimit() - this.time;
},
getCurrentProblemTimeLimit: function() {
return this.testProblems[this.getCurrentProblemIndex()].timeLimit;
},
getCurrentProblemIndex: function() {
return this.testProblems.length - 1;
},
addTestProblem: function(problem, timeLimit) {
var solution = math.eval(problem);
this.testProblems.push({problem: problem, timeLimit: timeLimit, solution: solution});
console.dir(this.testProblems);
},
testProblems: [],
updatePercentages: function(name) {
function round(num) {
return +(Math.round(num + "e+2") + "e-2");
}
console.log('updating percentages');
console.log('answers length ' + this.students[name].givenAnswers.length);
var timeSum = 0;
for(var i = 0; i < this.students[name].givenAnswers.length; i++ ) {
timeSum += this.students[name].givenAnswers[i].takenTime;
}
var timeAvg = timeSum / this.students[name].givenAnswers.length;
console.log('timeAvg for ' + name + ' ' + timeAvg);
this.students[name].avgTime = round(timeAvg);
var correctSum = 0;
for(var j = 0; j < this.students[name].givenAnswers.length; j++ ) {
if (this.students[name].givenAnswers[j].correct) {
correctSum++;
}
}
var correctAvg = correctSum / this.students[name].givenAnswers.length;
console.log('correctAvg for ' + name + ' ' + correctAvg);
this.students[name].avgCorrect = round(correctAvg) * 100;
},
addGivenStudentAnswer: function(name, answer, takenTime, index) {
console.log('adding answer ' + name + ' ' +answer+ ' ' + takenTime);
var correct = this.getCurrentSolution() == answer;
if (typeof this.students[name].givenAnswers[index] === 'undefined') {
this.students[name].givenAnswers[index] = ({
answer: answer,
takenTime: takenTime,
correct: correct
});
this.updatePercentages(name);
//console.dir(this.students[name].givenAnswers);
return true;
} else {
console.log('attempt at double answer. not saved');
return false;
}
},
addStudent: function(name) {
if (!(this.students[name])) {
this.students[name] = {
studentName : name,
avgTime: 0,
avgCorrect: 0,
givenAnswers: []
}
}
console.dir(this);
},
students: {}
};
console.dir(this);
},
deleteRoom: function(Id) {
delete this[Id];
console.log('room deleted from testResults');
}
};
// after test
var name = socket.userName;
var room = socket.room;
var created = testResults[room].created;
var students = testResults[room].students;
var problems = testResults[room].testProblems;
var test = new tests({
roomId : room,
created : created,
teacher : name,
students : students,
problems : problems
});
test.save(function(err, result) {
if (err) {console.log(err);}
else {
console.log('test saved to DB');
socket.emit('testSaved');
// delete from roomList
testRooms.deleteRoom(room, name);
// delete from resultObject
testResults.deleteRoom(room);
// answer
io.in(room).emit('room Closed');
}
});
route for reading a test from DB afterwars
router.get('/showtests/:roomId', function(req, res) {
if (req.user && req.user.role === 'teacher') {
tests.findOne({roomId: req.params.roomId}, {}, function(err, result) {
if (err) {console.log(err);}
res.render('showSingleTest', {user: req.user, testData: JSON.parse(JSON.stringify(result))});
})
} else {
res.render('customerror', { title: "Error", errMsg1: "error.error", errMsg2: "error.notLoggedIn" });
}
});
aaaaaand the jade
h2(data-i18n="markup.studentsAnswers")
each student in testData.students
.testViewSingleStudentAnswers.col-md-6
h3 #{student.studentName}
ol.answers
each answer in student.givenAnswers
if (answer)
if (answer.correct == true)
li.correct
span #{answer.answer}
|
span.floatRight (#{answer.takenTime}s)
else
li.wrong
span #{answer.answer}
|
span.floatRight (#{answer.takenTime}s)
else
li.noAnswer(data-i18n="markup.noAnswerGiven")
.testTotals
| #{student.avgCorrect}
span(data-i18n="markup.percentCorrect")
| ,
| #{student.avgTime}
span(data-i18n="markup.avgTime")
You can do like so:
function push_answer(answer){
answer = answer || "undefined"
array_of_answers.push(answer)
}
Now, the value is not undefined, but it's defined by the literal. You can replace it with some unicode character in case some answer can be "undefined".
Have a nice day!
Seems to be working without issue for me.
HTML:
<div id="content">
</div>
JS:
var answers = ["answer1","answer2",undefined,"answer3",undefined];
for(i=0;i<answers.length;i++) {
if(!answers[i]){
answers[i]="no answer";
}
}
document.getElementById('content').innerHTML = answers;
jsFiddle
My personal recomendation: "Never leave things to chance"
if the student doesn't choose an answer, you should fill that blank space with a '', because undefined is really annoying to handle, so in order to fill the gaps:
This will check if answer is "undefined" and fill the gap with a '' (blank), then, when you check that answer, is going to be more simple to evaluate...
if(answer)
answers[questionindex] = answer;
else
answers[questionindex] = '';

jQuery .each() multiplying "i"?

I'm trying to make a kind of newswire for a school project but I'm having a few problems with jQuery's .each() function. I'm trying to find a way to skip every 2nd array element in a loop.
Basically I have data from a NY Times API and got both title and abstract and push these into an array that I then loop and animate every once and awhile.
My problem is, I can't seem to find a way to get Title + Abstract (Index[0]+[1]) without the loop just moving to index[1] again. Now I knows in Javascript you can simply use a for (i=0; i < array.length; i+2) and thus skip every 2nd array element, but I haven't had any luck incorporating that. Any suggestions? :)
$(document).ready(function() {
var newsWire = [];
function loadNewswire() {
return $.getJSON('http://api.nytimes.com/svc/news/v3/content/all/all.json',
{'api-key': 'XXXXXXXXXXXXXXXXXXX'},
function(data) {
console.log(data)
var newsWireTemp = [];
for (var i = 0; i < data.results.length; i++) {
var breakingNews = data.results[i];
var breakingTitle = breakingNews.title.toUpperCase();
var breakingAbstract = breakingNews.abstract;
newsWireTemp.push(breakingTitle);
newsWireTemp.push(breakingAbstract);
}
newsWire = newsWireTemp;
});
}
loadNewswire().done(function () {
var items = newsWire;
$text = $('#newswiretxt span'),
delay = 10; //seconds
function loop (delay) {
$.each(items, function (i, elm){
$text.delay(delay*1E3).fadeOut();
$text.queue(function(){
$text.html(items[i]+ ": " +items[i+1]);
$text.dequeue();
});
$text.fadeIn();
$text.queue(function(){
if (i == items.length -1) {
loop(delay);
}
$text.dequeue();
});
});
}
console.log(items.length);
loop(delay);
});
});
Basically, just push the desired text concatenated into the array for the load function. Then as you iterate you can simply write the contents as is without messing with the iteration.
$(document).ready(function() {
var newsWire = [];
function loadNewswire() {
return $.getJSON('http://api.nytimes.com/svc/news/v3/content/all/all.json',
{'api-key': 'XXXXXXXXXXXXXXXXXXX'},
function(data) {
console.log(data)
var newsWireTemp = [];
for (var i = 0; i < data.results.length; i++) {
var breakingNews = data.results[i];
var breakingTitle = breakingNews.title.toUpperCase();
var breakingAbstract = breakingNews.abstract;
newsWireTemp.push(breakingTitle + ': ' + breakingAbstract);
}
newsWire = newsWireTemp;
});
}
loadNewswire().done(function () {
var items = newsWire;
$text = $('#newswiretxt span'),
delay = 10; //seconds
function loop (delay) {
$.each(items, function (i, elm){
$text.delay(delay*1E3).fadeOut();
$text.queue(function(){
$text.html(items[i]);
$text.dequeue();
});
$text.fadeIn();
$text.queue(function(){
if (i == items.length -1) {
loop(delay);
}
$text.dequeue();
});
});
}
console.log(items.length);
loop(delay);
});
});
See if this SO thread helps you.
From what I understand, you'd like to skip every other iteration, so checking i's parity to skip when appropriate should work.
For the lazy:
$.each(array, function(index, item) {
if(index % 2 === 0) return true; // This would skip
// Other logic
});
Let me know if it helps or not.
Instead of using two array indexes, use one object, var bn={};, add the two entries, bn.breakingTitle=breakingNews.title.toUpperCase(); and bn.breakingAbstract=breakingNews.abstract; then one push newsWireTemp.push(bn); so each entry in newsWire is more like newsWire[i].breakingTitle and newsWire[i].breakingAbstract.
One way to do it:
Fiddle: http://jsfiddle.net/q18dv4wr/
HTML:
<div id="test1">odds:</div>
<div id="test2">evens:</div>
JS:
var someData = [0,1,2,3,4,5,6,7,8,9,10];
var div1 = $('#test1');
var div2 = $('#test2');
$.each(someData,
function (index, value) {
if (index % 2 == 0) {
return;
}
else {
div1.append(' ' + value);
}
}
);
$.each(someData,
function (index, value) {
if (index % 2 != 0) {
return;
}
else {
div2.append(' ' + value);
}
}
);
EDIT: Seems I posted a moment too late. Someone else gave same idea already. =] Oh well.
You could do this:
$text.html(items[i]+ ": " +items[(i+=1)]);
But personally, I would push the breakingNews object into the array instead of having a different index for each property:
$(document).ready(function() {
var newsWire = [];
function loadNewswire() {
return $.getJSON('http://api.nytimes.com/svc/news/v3/content/all/all.json',
{'api-key': 'XXXXXXXXXXXXXXXXXXX'},
function(data) {
console.log(data)
var newsWireTemp = [];
for (var i = 0; i < data.results.length; i++) {
newsWireTemp.push(data.results[i]);
}
newsWire = newsWireTemp;
});
}
loadNewswire().done(function () {
var items = newsWire;
$text = $('#newswiretxt span'),
delay = 10; //seconds
function loop (delay) {
$.each(items, function (i, elm){
$text.delay(delay*1E3).fadeOut();
$text.queue(function(){
$text.html(items[i].title.toUpperCase()+ ": " +items[i].abstract);
$text.dequeue();
});
$text.fadeIn();
$text.queue(function(){
if (i == items.length -1) {
loop(delay);
}
$text.dequeue();
});
});
}
console.log(items.length);
loop(delay);
});
});
Try using .append() , checking if items[i + 1] is defined before appending items[i + 1] , else return empty string
$text.append(items[i] + (!!items[i+1] ? ":" + items[i+1] + " ": ""))
var items = "abcdefg".split("")
$.each(items, function(i, item) {
$("body").append(items[i] + (!!items[i+1] ? ":" + items[i+1] + " ": ""))
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Filtering on navigation properties for a set of value with toLowerCase

I have this JayData query (it can be checked at JSLQ playground):
northwind.Products
.filter( function( product ) {
return product.ProductName.toLowerCase() in ['tofu'];
} )
.toArray( function( products ) {
console.dir( products );
} );
For some unknown reasons this query produces incorrect filter expression:
http://services.odata.org/Northwind/Northwind.svc/Products?$filter=(tolowerProductName%20eq%20%27tofu%27)&$callback=parent.handleJSONP_21&$format=json
I highlighted incorrect parameter with bold above.
So you can see that we have tolowerProductName, but it should be tolower(ProductName), so the right filter query should looks like this:
http://services.odata.org/Northwind/Northwind.svc/Products?$filter=%28tolower%28ProductName%29%20eq%20%27tofu%27%29&$callback=parent.handleJSONP_21&$format=json
Is anybody know a workaround?
Update:
Issue occurs only when I use toLowerCase with "in [array]", so for example this query is working just fine:
northwind.Products
.filter( function( product ) {
return product.ProductName in ['Tofu'];
} )
.toArray( function( products ) {
console.dir( products );
} );
This query with toLowerCase is working just fine too:
northwind.Products
.filter( function( product ) {
return product.ProductName.toLowerCase() == 'Tofu';
} )
.toArray( function( products ) {
console.dir( products );
} );
Thank you!
Have you tried setting that expression to a variable and then checking for that in ['tofu']?
I found that incorrect filter expression produces this line of code (for query with 'in' operator):
context.data = temp + context.data.replace(/\(/g, '').replace(/\)/g, '');
Line 1542 in oDataProvider.js
I replaced it with this code:
context.data = temp + context.data;
And now everything is working as expected. Maybe I introduced other issues with this fix, but at least it works as expected for my queries.
So the VisitSimpleBinaryExpression function looks like this now:
VisitSimpleBinaryExpression: function (expression, context) {
context.data += "(";
//TODO refactor!!!
if (expression.nodeType == "in") {
Guard.requireType("expression.right", expression.type, $data.Expressions.ConstantExpression);
var paramValue = expression.right.value;
if (!paramValue instanceof Array) { Guard.raise(new Exception("Right to the 'in' operator must be an array value")); }
var result = null;
var orResolution = { mapTo: "or", dataType: "boolean", name: "or" };
var eqResolution = { mapTo: "eq", dataType: "boolean", name: "equal" };
paramValue.forEach(function (item) {
var idValue = item;
var idCheck = Container.createSimpleBinaryExpression(expression.left, idValue,
$data.Expressions.ExpressionType.Equal, "==", "boolean", eqResolution);
if (result) {
result = Container.createSimpleBinaryExpression(result, idCheck,
$data.Expressions.ExpressionType.Or, "||", "boolean", orResolution);
} else {
result = idCheck;
};
});
var temp = context.data;
context.data = '';
this.Visit(result, context);
//context.data = temp + context.data.replace(/\(/g, '').replace(/\)/g, '');
context.data = temp + context.data;
} else {
this.Visit(expression.left, context);
context.data += " ";
context.data += expression.resolution.mapTo;
context.data += " ";
this.Visit(expression.right, context);
};
context.data += ")";
},

Categories