I want to create a small web application that includes a function to search movies in Javascript. I want to make that when I search a movie's name, the function completes the rest of word. But I couldn't make it.
For example:
I wrote "bat" and function completes the "man". It is like google search. I wrote "stack" and google completes "overflow" in a dropdown list.
So here is my code in script:
var dataList = document.getElementById('json-datalist');
var input = document.getElementById('ajax');
var request = new XMLHttpRequest();
request.onreadystatechange = function(response) {
if (request.readyState === 4) {
var jsonOptions = JSON.parse(request.responseText);
jsonOptions.forEach(function(item) {
var option = document.createElement('option');
option.value = item;
dataList.appendChild(option);
});
else {
input.placeholder = "Couldn't load datalist options ";
}
}
};
request.open('GET', 'url', true);
request.send();
HTML code:
<form>
<p> Movie name: </p>
<input type="text" id="ajax" list="json-datalist" placeholder="e.g. Spider-Man">
<datalist id="json-datalist"></datalist>
I have verified the above code is working correctly. Now it could be a problem with how you are sending the data from the server.
The problem could be at below line.
option.value = item;
Check your json object, how you are sending data back. For example if there is a properties in object then you should use it as below;
option.value = item.value; => name of element
Related
I am very new to JS and I have a problem to create a searchable movie reviewer html page, it is very basic, I just want to know how to have the input box search the NYT API for the movie I am looking for, I wont have a problem putting the elements onto the page, I just want to know how to search properly. I expect I need a function that when the search button is clicked it requests from the site all movies with the words provided.
<div id="search">
<input type="text" id = "search">
<button onclick="search()">Search</button>
</div>
<textarea id="APIoutput" cols="90" rows="50"></textarea>
const ISFINISHED = 4;
const ISOK = 200;
var searchedMovie = document.getElementById("search").value;
function getJSONSync(url){
var response = "";
var xmlHttp = new XMLHttpRequest();
if(xmlHttp !== null){
xmlHttp.open("GET", url, false);
xmlHttp.send(null);
response = xmlHttp.responseText;
}
return response;
}
function getJSONAsync(url, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState === ISFINISHED && request.status === ISOK) {
callback(this);
}
};
request.open("GET", url);
request.send();
}
function search(searchedMovie){
var my_api_url = "https://api.nytimes.com/svc/movies/v2/reviews/search.json?query=" + searchedMovie + "&api-key=" + API;
return my_api_url;
}
function handleAPIresponse(response) {
var textArea = document.getElementById("APIoutput");
textArea.value = response.responseText;
}
getJSONAsync(my_api_url, handleAPIresponse);
ERRORS: Uncaught ReferenceError: my_api_url is not defined
Expected Results: (UNFORMATTED JSON THAT LOOKS LIKE THIS:)
{"status":"OK","copyright":"Copyright (c) 2021 The New York Times
Company. All Rights
Reserved.","has_more":false,"num_results":10,"results":[{"display_title":"The
Black Godfather","mpaa_rating":"TV-MA","critics_pick":0,"byline":"BEN
KENIGSBERG","headline":"‘The Black Godfather’ Review: The Music
Executive Who Made It All Happen"
I created an API with Node.js express and mongodb, working perfectly fine.
I have a delete function that works fine as well.
I have an empty HTML select, and I generate the different options by a performing a get request that create all options that I have in my mongodb database.
I would like to delete the selected option in my select but I'm struggling to find a way to get the id of the specific select option.
HTML
<select id="content-dropdown">
</select>
JS :
function showGames(url){
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (this.readyState == XMLHttpRequest.DONE && this.status == 200) {
var response = JSON.parse(this.responseText);
let i = 0;
for(i in response){
dropdown.innerHTML += '<option value="'+response[i].title+'" id="'+response[i]._id+'" class="game">'+response[i].title+'</option>';
}
}
};
request.open("GET", url);
request.send();
}
I managed to get all the id but when I use the delete function it delete the last option in the select.
I tried onchange / onclick event on the select but didn't manage to get it working.
Just set the identifier as the option value: value="'response[i]._id'" then listen to the onchange event of the select element and retrieve the current value with event.target.value in order to call the backend.
i'm trying to make auto complete with pure javascript.
Scenario is when type to input some letters it will search movies from omdbapi.
I make it like that:
i have input which users can search movies, i have get data from input value:
<input type="text" class="form-control" id="searchMovie" value="">
and here i get movies and make html markup with javascript for show these results in html:
var searchInput = document.getElementById("searchMovie");
// get movie
searchInput.onkeydown = function() {
var searchData = document.getElementById("searchMovie").value;
if (searchData.length >= 3 ) {
var request = new XMLHttpRequest();
request.open('GET', 'http://www.omdbapi.com/?s=' + searchData + '&apikey=000000', true);
request.onload = function () {
// Begin accessing JSON data here
var data = JSON.parse(this.response);
const wrapper = document.createElement('div');
app.appendChild(wrapper);
var results = data;
if (request.status >= 200 && request.status < 400) {
console.log(data);
Object.keys(data.Search).map(function(key, index) {
console.log(data.Search[index].Title);
const searchResultsContainer = document.createElement('div');
searchResultsContainer.setAttribute('class', 'row');
const h1 = document.createElement('h1');
h1.textContent = data.Search[index].Title;
wrapper.appendChild(searchResultsContainer);
searchResultsContainer.appendChild(h1);
console.log(searchResultsContainer);
});
} else {
console.log('error');
}
};
request.send();
}
};
everything work well but problem is:
when i try to delete keyword which i wrote and write new one results not disappear from html, i want change
You need to capture the change in the text input. Adding your code to a function and binding the input to oninput function. When there is a change in the value of the input it will rerun the api call. Furthermore, you need to clear out the old result.
<input type="text" class="form-control" id="searchMovie" value="" oninput"apiCall()">
<script>
function apiCall(){
var searchInput = document.getElementById("searchMovie");
// get movie
searchInput.onkeydown = function() {
var searchData = document.getElementById("searchMovie").value;
if (searchData.length >= 3 ) {
while (document.getElementsByClassName('autoComplete')[0]) {
document.getElementsByClassName('autoComplete')[0].remove();
}
var request = new XMLHttpRequest();
request.open('GET', 'http://www.omdbapi.com/?s=' + searchData + '&apikey=000000', true);
request.onload = function () {
// Begin accessing JSON data here
var data = JSON.parse(this.response);
var wrapper = document.createElement('div');
wrapper.className = "autoComplete";
app.appendChild(wrapper);
var results = data;
if (request.status >= 200 && request.status < 400) {
console.log(data);
Object.keys(data.Search).map(function(key, index) {
console.log(data.Search[index].Title);
const searchResultsContainer = document.createElement('div');
searchResultsContainer.setAttribute('class', 'row');
const h1 = document.createElement('h1');
h1.textContent = data.Search[index].Title;
wrapper.appendChild(searchResultsContainer);
searchResultsContainer.appendChild(h1);
console.log(searchResultsContainer);
});
} else {
console.log('error');
}
};
request.send();
}
}
</script>
That should remove the wrapper element you added and its children and populate a new one with new data. I can't really test this to make sure it works as I can not see the rest of your code. But it should work. if not I can help you to figure out any errors.
Also, I would consider making wrapper just a hidden div that you can easily clear and unhide when needed. It would be much easier and you wouldn't need to add and remove so many elements. just wrapper.innerHTML = ""; then wrapper.innerHTML = newRowSet; and done
Instead of setting h1.textContent = data.Search[index].Title; update this to h1.innerHTML = data.Search[key].Title;
I am trying to create a simple webpage containing comments in a table. I can successfully populate it by calling following function on "window.onload" event.
function FillCommentsTable() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var comments = JSON.parse(this.responseText);
var i = 0;
var old_tbody = document.getElementById("comments");
var new_tbody = document.createElement("tbody");
for (i = 0; i < comments.length; i++) {
var row = new_tbody.insertRow(-1);
var id = row.insertCell(0);
var user = row.insertCell(1);
var comment = row.insertCell(2);
var timestamp = row.insertCell(3);
id.innerHTML = comments[i].Id;
user.innerHTML = comments[i].User;
comment.innerHTML = comments[i].Comment;
timestamp.innerHTML = comments[i].Timestamp;
}
old_tbody.parentNode.replaceChild(new_tbody, old_tbody);
}
};
xhttp.open("GET", "API/get_comments.php", true);
xhttp.send();
}
The webpage also have functionality to submit and delete comment with simple form calling the API that manipulates the database storing the comments. The wanted functionality here is that after the submit/delete form has been submitted and called the API the page is reloaded and the table updated. To achieve this I have tried to reload the page on submit with:
<form action="API/delete_comment.php" method="post"
onsubmit="window.location.reload()">
<input type="number" name="id">
<input type="submit" value="Delete">
</form>
but this seems to have no effect except that the expected call to the API is sent. This also only occurs when trying to update the table with a form since just binding a button:
<button onclick="window.location.reload()">Load comments</button>
works as intented and updates the table correctly. Is it not possible to sent both the GET for the webpage and the POST to the API triggered on the same event or what am I missing here?
The point of AJAX is to be able to communicate with the server without having to reload the page...
Submit the form with AJAX instead and then simply call your FillCommentsTable again.
<form action="#" method="post" onsubmit="return deleteComment()">
<input type="number" name="id">
<input type="submit" value="Delete">
</form>
function deleteComment() {
var id = document.querySelector("input[name='id']");
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
FillCommentsTable();
}
};
xhttp.open("POST", "API/delete_comment.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("id="+encodeURIComponent(id.value));
return false;
}
Edit:
The above successfully sends the GET request retrieving the data. In addition to these changes I also added
new_tbody.setAttribute("id","comments");
in the FillCommentsTable function. The mistake of omitting this caused the comments table body to lose its name on the first reload which then caused subsequent calls to FillCommentTable to have no effect since there is no tbody called "comments" ...
Ideally, you should have two data call functions, one to GET data from DB and one to POST data to your DB.
function FillCommentsTable() {
//Function Stuff
}
function AddNewComment() {
//Function Stuff
}
You have a few options on how to process the data:
On POST of a new item, after you receive a status of 200, call your
FillCommentsTable function.
If you have an array storing your comments on the client side, as
you make your POST call and after you receive a status of OK,
array.push(newComment)
You can also take advantage of Promises (Browser support, ECMA2015) to ensure sequencing. I will leave it at a resource link for now as its not exactly within scope of the OP.
I have a form with 2 inputs, where the 1st input has a datalist attribute.
<div class="col-xs-4">
<input name="description" type="text" id="ajax" list="json-datalist">
<datalist id="json-datalist"></datalist>
</div>
<div class="col-xs-2">
<input type="text" name="product" />
</div>
the JSON file has this format
[ {
"product":"1235",
"description":"description 1"
},
{
"product":"1325",
"description":"description 2"
},
...
]
What I want is when the user selects one of the description, then the product to be added in the 2nd input..
here is the code for the javascript where loads the JSON file to the form
var dataList = document.getElementById('json-datalist');
var input = document.getElementById('ajax');
var request = new XMLHttpRequest();
request.onreadystatechange = function(response) {
if (request.readyState === 4) {
if (request.status === 200) {
// Parse the JSON
var jsonOptions = JSON.parse(request.responseText);
// Loop over the JSON array.
jsonOptions.forEach(function(item) {
// Create a new <option> element.
var option = document.createElement('option');
// Set the value using the item in the JSON array.
option.value = item.description;
//<--
// Add the <option> element to the <datalist>.
dataList.appendChild(option);
});
// Update the placeholder text.
input.placeholder = "e.g. datalist";
} else {
// An error occured :(
input.placeholder = "Couldn't load datalist options :(";
}
}
};
// Update the placeholder text.
input.placeholder = "Loading options...";
// Set up and make the request.
request.open('GET', 'myfile.json', true);
request.send();
How can I add the item.product as a value to the second input, when the item.description is selected?
Set product in the data attribute of datalist like following.
option.value = item.description; //after this line
option.setAttribute('data-product', item.product);
And in description change event set product to second input like following using jquery.
$('#ajax').change(function() {
var description = $(this).val();
var product = $('#json-datalist > option[value="' + description + '"]').data('product');
$('input[name=product]').val(product);
});
Full JS code given below. Hope this helps.
var dataList = document.getElementById('json-datalist');
var input = document.getElementById('ajax');
var request = new XMLHttpRequest();
request.onreadystatechange = function (response) {
if (request.readyState === 4) {
if (request.status === 200) {
// Parse the JSON
var jsonOptions = JSON.parse(request.responseText);
// Loop over the JSON array.
jsonOptions.forEach(function (item) {
// Create a new <option> element.
var option = document.createElement('option');
// Set the value using the item in the JSON array.
option.value = item.description;
option.setAttribute('data-product', item.product);
//<--
// Add the <option> element to the <datalist>.
dataList.appendChild(option);
});
// Update the placeholder text.
input.placeholder = "e.g. datalist";
} else {
// An error occured :(
input.placeholder = "Couldn't load datalist options :(";
}
}
};
// Update the placeholder text.
input.placeholder = "Loading options...";
// Set up and make the request.
request.open('GET', 'myfile.json', true);
request.send();
$(function() {
$('#ajax').change(function() {
var description = $(this).val();
var product = $('#json-datalist > option[value="' + description + '"]').data('product');
$('input[name=product]').val(product);
});
});
You can create your <option> element with some other attribute that indicates the product, and then use that attribut to copy it into the second input.
request.onreadystatechange = function(response) {
if (request.readyState === 4) {
if (request.status === 200) {
// Parse the JSON
var jsonOptions = JSON.parse(request.responseText);
// Loop over the JSON array.
jsonOptions.forEach(function(item) {
// Create a new <option> element.
var option = document.createElement('option');
// Set the value using the item in the JSON array.
option.value = item.description;
$(option).attr('data-product',item.product);//THIS IS THE NEW LINE
//<--
// Add the <option> element to the <datalist>.
dataList.appendChild(option);
});
// Update the placeholder text.
input.placeholder = "e.g. datalist";
} else {
// An error occured :(
input.placeholder = "Couldn't load datalist options :(";
}
}
};
And then, for copying it, if you are using JQuery:
$('input#ajax').change(function(){
$('input[name="product"]').val($('#json-dataList').find('option:selected').attr('data-product'));
});