How to parse a JSON response in jQuery? - javascript

I'm creating a small web-app for my girlfriend and I that will allow us to keep track of the movies we want to watch together. To simplify the process of adding a movie to the list, I'm trying to use TheMovieDatabase.org's API (supports JSON only) to allow us to search for a movie by title, let the database load a few results, and then we can choose to just add a movie from the database or create our own entry if no results were found.
I'm using jQuery to handle everything and, having never used JSON before, am stuck. I wrote a short bit of code to get the JSON based on my search query, and am now trying to populate a <ul> with the results. Here's what I have.
var TMDbAPI = "https://api.themoviedb.org/3/search/movie";
var moviequery = $("#search").val();
var api_key = "baab01130a70a05989eff64f0e684599";
$ul = $('ul');
$.getJSON( TMDbAPI,
{
query: moviequery,
api_key: api_key
},
function(data){
$.each(data, function(k,v) {
$ul.append("<li>" + k + ": " + v + "</li>");
}
);
});
The JSON file is structured as
{
"page":1,
"results":[
{
"adult":false,
"backdrop_path":"/hNFMawyNDWZKKHU4GYCBz1krsRM.jpg",
"id":550,
"original_title":"Fight Club",
"release_date":"1999-10-14",
"poster_path":"/2lECpi35Hnbpa4y46JX0aY3AWTy.jpg",
"popularity":13.3095569670529,
"title":"Fight Club",
"vote_average":7.7,
"vote_count":2927
}, ...
"total_pages":1,
"total_results":10
}
but all I'm getting is
page: 1
results: [object Object], ...
total_pages: 1
total_results: 10
I've searched quite extensively on the Internet for a solution, but with the little knowledge I have of JSON I wasn't able to learn much from the various examples and answers I found scattered about. What do?

It looks like what you'd like to do is write out some properties of each movie in the list. This means you want to loop over the list in data.results, like this:
// Visit each result from the "results" array
$.each(
data.results,
function (i, movie) {
var $li = $('<li></li>');
$li.text(movie.title);
$ul.append($li);
}
);
This will make a list of movie titles. You can access other properties of movie inside the each function if you want to show more elaborate information.
I added the title to the li using $li.text rather than simply doing $('<li>' + movie.title + '</li>') since this will avoid problems if any of the movie titles happen to contain < symbols, which could then get understood as HTML tags and create some funny rendering. Although it's unlikely that a movie title would contain that symbol, this simple extra step makes your code more robust and so it's a good habit to keep.

You need to traverse the results object. In the $.each function change data for data.results

You can use a simple for loop to iterate over the list/array. in the example below i am appending a list item containing the value of the key results[i].title. you can append the values of as many valid keys as you would like to the div.
var TMDbAPI = "https://api.themoviedb.org/3/search/movie";
var moviequery = $("#search").val();
var api_key = "baab01130a70a05989eff64f0e684599";
$ul = $('ul');
$.getJSON( TMDbAPI,
{query: moviequery,api_key: api_key},function(data){
var results = data.results;//cast the data.results object to a variable
//iterate over results printing the title and any other values you would like.
for(var i = 0; i < results.length; i++){
$ul.append("<li>"+ results[i].title +"</li>");
}
});

html
<input id="search" type="text" placeholder="query" />
<input id="submit" type="submit" value="search" />
js
$(function () {
$("#submit").on("click", function (e) {
var TMDbAPI = "https://api.themoviedb.org/3/search/movie";
var moviequery = $("#search").val();
var api_key = "baab01130a70a05989eff64f0e684599";
$.getJSON(TMDbAPI, {
query: moviequery,
api_key: api_key
},
function (data) {
$("ul").remove();
var ul = $("<ul>");
$(ul).append("<li><i>total pages: <i>"
+ data.total_pages + "\n"
+ "<i>current page: </i>"
+ data.page
+ "</li>");
$.each(data.results, function (k, v) {
$(ul).append("<li><i>title: </i>"
+ v.original_title + "\n"
+ "<i>release date: </i>" + v.release_date + "\n"
+ "<i>id: </i>" + v.id + "\n"
+ "<i>poster: </i>"
+ v.poster_path
+ "</li>");
});
$("body").append($(ul))
});
});
});
jsfiddle http://jsfiddle.net/guest271314/sLSHP/

Related

Trying to get strings from specific sites (same domain) and place them in a chart

I have a chrome extension that, right now, is purely a cosmetic addition to a Counter-Strike forum and matchmaking site. I'm trying to implement some Javascript to show players ranks when looking at the statistics of a match. Currently, it looks like this: statistics page imgur
I'm trying to add a new column to the left of where players' names appear that shows their ranks. Ranks are currently only stored on the players' profile page, so I'm trying to write code that will go to each players' profile (currently hyperlinked to their name), get their rank and display that as text.
I have 0 understanding of Javascript despite trying to learn it many times but this is a heavily requested feature and I'd like to implement it for my users.
sample statistics page
sample profile page
As of a few months ago, the following code worked:
function findRanks(i) {
var allUsers = $(document).find("#body-match-total" + i + " tr");
$.each($(document).find("#body-match-total" + i + " tr"), function(index, value){
var userLink = "https://play.esea.net/users/" + allUsers[index].children[0].children[1].innerHTML
$.get(userLink, function(data) {
var parsed = $('<div/>').append(data);
rank = $(parsed).find("#rankGraph h1").text();
allUsers[index].children[0].children[1].innerHTML += " (" + rank + ") ";
});
});
}
findRanks(1);
findRanks(2)
Was missing a bracket. Thanks to some random guy on ESEA forums for the help.
Here is the functional code for people with the same issue
function findRanks(i) {
var allUsers = $(document).find("#body-match-total" + i + " tr");
$.each($(document).find("#body-match-total" + i + " tr"), function(index, value){
var userLink = "https://play.esea.net/users/" + allUsers[index].children[0].children[1].innerHTML
$.get(userLink, function(data) {
data = data.replace(/<img[^>]*>/g,"");
var parsed = $('<div/>').append(data);
rank = $(parsed).find("#rankGraph h1").text();
allUsers[index].children[0].children[1].innerHTML += " (" + rank + ") ";
});
});
}
findRanks(1);
findRanks(2);

Loop through json received from wikipedia api using .each()

Trying to loop through json received from wikipedia api using .each(), but it returns undefined on everything. What have I missed?
Here is codepen: https://codepen.io/ekilja01/pen/pRerpb
Here is my HTML:
<script src="https://use.fontawesome.com/43f8201759.js">
</script>
<body>
<h2 class="headertext">WIKIPEDIA <br> VIEWER </h2>
<div class="row">
<div class="col-10-md">
<input class="searchRequest blink_me" id="cursor" type="text" placeholder="__"></input>
</div>
<div class="searchIcon col-2-md"> </div>
</div>
<div class="results">
</div>
</body>
Here is jQuery:
$(document).ready(function() {
var icon = "<i class='fa fa-search fa-2x'></i>";
$('#cursor').on("keydown", function() {
$(this).removeClass("blink_me");
var searchIcon = $(".searchIcon");
searchIcon.empty();
if ($(".searchRequest").val().length > 0) {
searchIcon.append(icon);
}
searchIcon.on("click", function() {
console.log("clicked!");
var search = $(".searchRequest").val();
var url = "https://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=" + search + "&format=json&callback=?";
$.ajax({
dataType: "jsonp",
url: url,
success: function(data) {
$("ul").empty();
$.each(data[1], function(value, index) {
$(".results").append("<ul><li><h3>" + data[1][index] + "</h3><p>" + data[2][index] + " Read More...</p></li></ul>");
});
searchIcon.empty();
}
});
});
});
});
in $.each(data[1], function(value, index) you've to switch value to index and viceversa like this $.each(data[1], function(index, value)
For reference: jQuery.each()
I have gone through your code. Please change
$.each(data[1], function(value, index) to
$.each(data[1], function(index, value)
This is a bit of a crude way of going about this but one way I verify that the information is what it should be is to iterate with a nested for loop.
It may not solve the immediate problem, but its a way to go to understand how this thing is working.
for(var i = 0; i < data.length; i++)
{
///alert(data[i]); //See what data you're passing to WIKIPEDIA's API
for(var j = 0; j < data[i].length; j++)
{
//See what data WIKIPEDIA's API is passing to you
//From here, you can determin which value (j) to us (e.g. j = 0 is the Title)
//Once you hav that, you can use it to append to you 'results' class
alert('i = ' + i + '| j = ' + j);
alert('data = ' + data[i][j]);
///////////
//$(".results").append("<ul><li><h3>" + data[i][j] + "</h3><p>"
//+ data[i][j] + "<a href=\"" + data[i][j]
//+ "\"> Read More...</a></p></li></ul>");
///////////
}
While this is not a fix for your problem (fixed by Roberto Russo), there is something else going on that's probably not intended: you register searchIcon.on("click") callback inside $('#cursor').on("keydown") callback. What this means is that every time keydown event fires on the $(#cursor) element, a new listener will be added to searchIcon.on("click"). That's why you see "clicked!" printed multiple times for just one click. Also, if you check the network log, you'll see multiple requests sent to the wiki api for the same reason.
I'd suggest moving searchIcon.on("click") outside $('#cursor').on("keydown").
You need to swap value and index to this:
$.each(data[1], function(index, value)
Make sure whenever you call $.each() function, you cannot change the order of the arguments.
Example : $.each(arryName, function(index, value)
index = The index associates with arryName
value = The value associates with the index

How do I move 1 object in an array to another array in javascript and then show both in a listview ( jquery )

So for a school assignment I need to write a basic mobile web application, using jquery and javascript. I need to make a page where you can add a title and author of a book and add it to a list using local storage. So far so good but I want to make 2 lists, one for books to read and one for read books. Now I made the listview with a split icon so when it's clicked that book should move to the other list. That listview contains also a split icon which should remove the book in it's whole.
The adding part is working and the added books are displayed in the listview but I can't seem to get the button working to change the list the book is in. Please help me I'm loosing my mind. Here is my html and javascript code:
<!-- OVERVIEW -->
<section id="overview" data-role="page" data-theme="b">
<!-- CONTENT -->
<div class="ui-content">
<div>
Add a new book
<h1>Books to read</h1>
</div>
<ul id="booksToRead" data-role="listview" data-split-icon="check" data-theme="b" data-split-theme="b" data-inset="true"></ul>
<h1>Read books</h1>
<ul id="readBooks" data-role="listview" data-split-icon="delete" data-theme="b" data-split-theme="b" data-inset="true"></ul>
</div>
</section>
And the javascript code
function add() {
// Retrieve the entered form data
var title = $('[name="bookTitle"]').val();
var author = $('[name="bookAuthor"]').val();
var book = {title:title, author:author};
// Fetch the existing books to read
var booksToRead = getObjects("booksToRead");
// Push the new item into the existing list
booksToRead.push(book);
// Store the new list
saveObjects(booksToRead, "booksToRead");
//reset textfields
$('[name="bookTitle"]').val('');
$('[name="bookAuthor"]').val('');
// Load the page with all the books
window.location.href = "#overview";
}
function getObjects(name) {
// See if objects are inside localStorage
if (localStorage.getItem(name)) {
// If yes, then load the objects
var objects = JSON.parse(localStorage.getItem(name));
} else {
// Make a new array of objects
var objects = new Array();
}
return objects;
}
function saveObjects(objects, name) {
// Save the list into localStorage
localStorage.setItem(name, JSON.stringify(objects));
}
function read(dit){
var readBooks = getObjects("readBooks");
var booksToRead = getObjects("booksToRead");
var book = booksToRead[dit];
// Push the new item into the existing list
readBooks.push(book);
// Store the new list
saveObjects(readBooks, "readBooks");
//Delete from the old list
deleteme(dit, "booksToRead");
//Reload page
window.location.reload();
}
function deleteme(dit, listName) {
// Fetch existing objects
var objects = getObjects(listName);
// Delete given object from list
objects.splice(dit, 1);
// Save list
saveObjects(objects, listName);
//Reload page
window.location.reload();
}
function loadPage() {
// Fetch the existing objects
var booksToRead = getObjects("booksToRead");
var readBooks = getObjects("readBooks");
// Clear the lists
$('#booksToRead').find('li').remove();
$('#readBooks').find('li').remove();
// Add every object to the objects list
$.each(booksToRead, function(index, item) {
var title = item.title;
var author = item.author;
$('#booksToRead').append('<li><a>' + title + ' - ' + author + '</a><a class="read" onclick="read(' + booksToRead.index + ')" data-transition="none"></a></li>');
});
$.each(readBooks, function(index, item) {
var title = item.title;
var author = item.author;
var listName ="readBooks";
$('#readBooks').append('<li><a>' + title + ' - ' + author + '</a><a class="delete" onclick="delete(' + readBooks.index + ', ' + listName + ')" data-transition="none"></a></li>');
});
$('#booksToRead').listview();
$('#booksToRead').listview("refresh");
$('#readBooks').listview();
$('#readBooks').listview("refresh");
}
$(document).on('pagebeforeshow', '#overview', function(event) {
loadPage();
});
I've think i got your error, in your $.each loop try removing your
booksToRead.index
// and
readBooks.index
for just
index
So, your $.each loops will look like that:
$.each(booksToRead, function(index, item) {
var title = item.title;
var author = item.author;
$('#booksToRead').append('<li><a>' + title + ' - ' + author + '</a><a class="read" onclick="read(' + index + ')" data-transition="none">ddddd</a></li>');
});
$.each(readBooks, function(index, item) {
var title = item.title;
var author = item.author;
var listName ="readBooks";
$('#readBooks').append('<li><a>' + title + ' - ' + author + '</a><a class="delete" onclick="delete(' + index + ', ' + listName + ')" data-transition="none"></a></li>');
});
Your are trying to get the property "index" of the object booksToRead while what you need to do is get the index param property of the $.each loop function, so you will get the correct index of the book you want to move.
You don't get error in the console because booksToRead.index === undefined and don't generates any exception, so, your index become ..."onclick="read(undefined)"...
Hope i've helped, good luck with your project!

Grouping selectors in 1 action

I'm having a simple issue with grouping jQuery selectors in 1 action.
For example I have a list of variables like:
var searchresults = '#search-results';
var event_two = '#event-two';
var competition_three = '#competition-three';
var apparatus_four = '#apparatus-four';
After triggering on change event I have something like this:
$("#event_two, #competition_three, #apparatus_four").empty();
No problem is I can't get it working. I've tried already in a lot of different ways.
This is how the code snippet of the first part of my code:
$(document).on('change', '#discipline-one', function() {
var discipline = $(this).val();
// event_two.empty();
// competition_three.empty();
// apparatus_four.empty();
$("#event_two, #competition_three, #apparatus_four").empty();
$("#event_two").append("<option selected='true' disabled='disabled'>Please select an event</option>");
$("#competition_three").append("<option selected='true' disabled='disabled'>Please choose from above</option>");
$("#apparatus_four").append("<option selected='true' disabled='disabled'>Please choose from above</option>");
$("#event_two").attr("disabled",true);
$("#competition_three").attr("disabled",true);
$("#apparatus_four").attr("disabled",true);
$.get("getEvents.php?discipline=" + discipline, function(data) {
var vals = jQuery.parseJSON(data);
if(data) {
$("#event_two").attr("disabled",false);
$("#event_two").attr("autofocus",true);
}
if($.isArray(vals['Event'])) {
$.each(vals['Event'], function(k,v){
$("#event_two").append("<option value='"+v['id']+"'>" + v['name'] + "</option>");
});
} else {
$("#event_two").append("<option value='"+vals['Event']['id']+"'>" + vals['Event']['name'] + "</option>");
}
});
});
Thank you in advance.
I think you have a typo:
Here you say:
$("#event_two, #competition_three, #apparatus_four").empty();
Where you define id's with underscores.
Here you say:
var searchresults = '#search-results';
var event_two = '#event-two';
var competition_three = '#competition-three';
var apparatus_four = '#apparatus-four';
Where your id's doesn't contain underscores.
I think you mean: (UPDATE)
$(event_two + ', ' + competition_three + ', ' + apparatus_four).empty();
Like #VDesign said, you define ID's with underscores, but in your variables, you have hyphens. So the following won't work:
$("#event_two, #competition_three, #apparatus_four").empty();
But when you want to select multiple objects, you have to have one big string with commas, like so:
$(event_two + ',' + competition_three + ',' + apparatus_four).empty();
See http://api.jquery.com/multiple-selector/ for more details on multiple selectors.
You could even do something like this:
$([ event_two, competition_three, apparatus_four ].join(',')).empty();

js/jquery iterate through html elements to dynamically build a string

I'd like to build a string based on values defined in an html form only if they have been populated. I've successfully parsed the form fields and dropdown with a for loop ($.each()) but my ultimate goal is to dynamically build a string with the results. The string is being used to create a REST query, this is currently the only way to search based on our technologies. Does anyone have a recommended solution?
thx in advance
sample html element:
<input data-param=" prefix like '%" data-name="prefix" class="prefix uno" type="text" placeholder="pre">
working btn click event loop to capture filled in form fields:
var children = $(this).parent().children('.uno');
$.each(children, function(i, val){
if($(val).val() !== ''){
console.log($(val).data('name') + " "+ $(val).data('param') + " " + $(val).val());
}
});
goal:
var newString = field1.param + field1.val + '% ' + field2.param + field2.val + '% ';
translated:
var newString = prefix like '%01%' and name like '%tree%';
Thanks David Fregoli for the jquery serialize reference, that was close, but the solution ended up being to place the strings into a single array, change it toString(), and remove the ',' from the new string.
code:
var samp = [],
thisVal = $(this).parent().children('.uno');
$.each(thisVal, function(i, val){
if($(val).val() !== ''){
samp.push(
$(val).data('param'),
$(val).val(),
$(val).data('close')
);
}
});
itQuery.where = samp.toString().replace( /,/g , '');
result search string:
"number like '%08%' and field = 34"

Categories