How to change an image using an onclick button - javascript

I cannot get my images to change when I click each button name. Anyone know what the issue is with my code?
It's not letting me put my code in the description.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hmwk02</title>
</head>
<body>
<h1>Octocats</h1>
<img id="octocats" src= "https://octodex.github.com/images/original.png" alt="octocat" width="150"/>
<div id="buttons"></div>
<script>
let names= ["Castello", "Grinchtocat", "Mummytocat", "Adventure-Cat"];
let urls= ["https://octodex.github.com/images/catstello.png",
"https://octodex.github.com/images/grinchtocat.gif",
"https://octodex.github.com/images/mummytocat.gif",
"https://octodex.github.com/images/adventure-cat.png"];
let lines = "";
for(let i = 0; i< names.length; i++){
lines += '<button onlick="showPicture(' + i +')">' + names[i] + '</button><br/>'
}
document.getElementById("buttons").innerHTML = lines;
console.log(lines);
</script>
<script src="octocats.js"></script>
</body>
function showPicture(i) {
document.getElementById("octocat").src = urls[i];
console.log(i);
}

Your code is fine other than syntax errors, you misspelled onclick in your button tag and you misspelled the ID for the picture--it should be document.getElementById("octocats") not document.getElementById("octocat")
corrected code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hmwk02</title>
</head>
<body>
<h1>Octocats</h1>
<img id="octocats" src= "https://octodex.github.com/images/original.png" alt="octocat" width="150"/>
<div id="buttons"></div>
<script>
let names= ["Castello", "Grinchtocat", "Mummytocat", "Adventure-Cat"];
let urls= ["https://octodex.github.com/images/catstello.png",
"https://octodex.github.com/images/grinchtocat.gif",
"https://octodex.github.com/images/mummytocat.gif",
"https://octodex.github.com/images/adventure-cat.png"];
let lines = "";
for(let i = 0; i< names.length; i++){
lines += '<button onclick="showPicture(' + i +')">' + names[i] + '</button><br/>'
}
document.getElementById("buttons").innerHTML = lines;
console.log(lines);
</script>
<script>
function showPicture(i) {
document.getElementById("octocats").src = urls[i];
console.log(i);
}</script>
</body>
working codepen: https://codepen.io/anon/pen/YBYxgr

An alternative to using the for loop would be to map() the names array and simply use createElement() method to create a new <button> element with a click listener for each item in your names array (you should avoid using inline on* handlers (onclick, oninput, etc) and use IDs and event listeners instead).
Check and run the following Code Snippet for a practical example of what I have described above:
let names= ["Castello", "Grinchtocat", "Mummytocat", "Adventure-Cat"];
let urls= ["https://octodex.github.com/images/catstello.png", "https://octodex.github.com/images/grinchtocat.gif", "https://octodex.github.com/images/mummytocat.gif", "https://octodex.github.com/images/adventure-cat.png"];
names.map((e, i) => { // add function to each element in "names" array
let name = document.createElement("button"); // create <button> element for each item in "names" array
name.id = i; // assign respective index as id of each element
name.textContent = e; // assign item string as button text content
name.addEventListener("click", () => document.getElementById("octocats").src = urls[i]); // add click listener to each <button> that changes image src on click
document.getElementById("buttons").appendChild(name); // append the <button> elements to your `#buttons` div.
});
<h1>Octocats</h1>
<img id="octocats" src= "https://octodex.github.com/images/original.png" alt="octocat" width="150"/>
<div id="buttons"></div>

Related

I'm trying to append an image from a javascript object Array onto my html page

So I was able to create a movie class array with 4 constructors, and a for loop with 3 iterations that represent three different movies. On the html page this allows the user to open a dropdown selection and pick one of the three movies. After hitting the submit button I want to display all the info for all the movie they selected including its image which is the difficult part. Here is my code so far:
<!DOCTYPE html>
<html>
<head>
<script src="jquery.js"></script>
<script src="Script.js"></script>
</head>
<body>
<form >
<select>
</select>
<button onclick="showDetail()">Submit</button>
</form>
<p></p>
</body>
</html>
class movie {
name;
price;
image;
genre;
constructor(x,y,z,a){
this.name = x;
this.price = y;
this.image = z;
this.genre = a;
}
}
let movies =[];
movies[0]= new movie("Deadpool", "$6.95","Image/Deadpool.jpg", "Superhero, Action");
movies[1]= new movie("Titanic", "$4.95", "" , "Romance, Drama");
movies[2]= new movie("Spiderman 3", "$6.95","", "Superhero, Action");
$(document).ready(function() { console.log( "ready!");
for (var i = 0; i < 3; i++){
movies[0].image= "Image/Deadpool.jpg";
movies[1].image= "Image/Titanic.jpg";
movies[2].image= "Image/Spiderman.jpg";
$("select").append(`<option>${movies[i].name}</option>`); console.log(i) }});
function showDetail(){
for (var i = 0; i < 3; i++){
$("p").append(`${movies[i].price},${movies[i].genre}, ${movies[i].image}`);
}
}
You can append HTML using .append() but I would not recommend appending it to a paragraph tag, and using the paragraph selector, try doing this:
<div id="details"> </div>
Add the above instead of the paragraph tag and then in jquery you could so something like:
$('#details').append(`<h1> ${movies[i].price} </h1> <p> ${movies[i].genre} </p> <img src="${movies[i].image}" alt="movie" />

separate elements from google books api

it was a long time ago that I didn’t program in javascript so I decided to make a project of a "bookcase" to manage read books and that I want to read more I have difficulty with how to separate the elements to personalize the style because it selects all the results of the api in one just div.
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="script.js"></script>
<link rel="stylesheet" href="./css/bookcase.css">
<title>project</title>
</head>
<body>
<div id="content">
</div>
<script src="https://www.googleapis.com/books/v1/volumes?q=clean+code&callback=handleResponse></script>
</body>
</html>
js
function handleResponse(response) {
for (var i = 0; i < response.items.length; i++) {
var item = response.items[i];
var book = document.getElementById('content')
book.innerHTML += "<br>" + '<img src=' + response.items[i].volumeInfo.imageLinks.thumbnail + '>';
book..innerHTML += "<br>" + item.volumeInfo.title;
book..innerHTML += "<br>" + item.volumeInfo.authors;
Clean answer - you should use document.appendChild(child) instead of innerHTML method.
Also, there are few recently added js methods that can help you operate large JSON objects - map, reduce, filter.
I added example, how you can clean original object to smaller array, and insert items from that array into html-page.
function demo (obj) {
// getting all items from object
const book = Object.keys(obj).map(item => obj['items']).reduce(
(acc,rec, id, array) => {
// getting Cover, Title, Author from each item
let singleBookCover = rec[id].volumeInfo.imageLinks.thumbnail;
let singleBookTitle = rec[id].volumeInfo.title;
let singleBookAuthor = rec[id].volumeInfo.authors[0];
// Creating new array only with Cover, Title, Author
return [...acc, {singleBookCover, singleBookTitle, singleBookAuthor}]
},
[]
).forEach( item => {
// For each item on our array, we creating h1
let title = document.createElement('h1');
title.textContent = `${item.singleBookTitle} by ${item.singleBookAuthor}`;
// img
let img = document.createElement('img');
img.src = item.singleBookCover;
img.alt = `${item.singleBookTitle} by ${item.singleBookAuthor}`;
// and div wrapper
let container = document.createElement('div');
// adding our child elements to wrapper
container.appendChild(title).appendChild(img);
// adding our wrapper to body
document.body.appendChild(container);
})
return book
}
Hope my answer will help you)
function handleResponse(obj) {
const container = document.getElementById("container")
obj.items.forEach((rec, index) => {
let singleBookCover =
rec.volumeInfo.imageLinks && rec.volumeInfo.imageLinks.smallThumbnail;
let singleBookTitle = rec.volumeInfo.title;
let singleBookAuthor = rec.volumeInfo.authors[0];
let book = document.createElement("div");
book.className = "book"
book.innerHTML = `
<div><h1>${singleBookTitle}<h1>
<p>${singleBookAuthor}</p>
<img src="${singleBookCover}"></img>
</div>
`
content.appendChild(book)
});
}
<div id="content" class="books">
</div>
<script src="https://www.googleapis.com/books/v1/volumes?q=clean+code&callback=handleResponse"></script>

Listing in Javascript

How can I stop this Javascript code from passing the last number of the iteration to the delete function?
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="lista"></div>
</body>
<script type="application/javascript">
var dados = ['vassoura','lixo','papel'];
function deletar(elemento){
console.log(elemento);
}
function listar(){
var div = document.getElementById('lista');
for(i in dados){
campo = document.createElement("output");
button = document.createElement("button");
button.addEventListener("click",()=>{
deletar(dados[i]);
});
button.innerHTML="deletar";
div.appendChild(campo);
div.appendChild(button);
console.log(i);
campo.value = dados[i]+" ";
console.log(dados[i]);
}
}
listar();
</script>
it is passing the last number corresponding to iteration because when I click on the button the iteration has already been made and finished
Looks like here is a common mistake with a variable scope.
Simplest way is to either use closure or replace for(i in dados) at least with for(let i in dados)
First ,get the length of dados. and check when i = dados_length (last element) then skip that code which you want to skip.

Bold text in body using javascript

This code is attempting to highlight (by adding 'bold' tag) some characters that are in the HTML body. (These are specified in the JS function)
But instead of the text becoming bold, I get the 'bold' tag as the result in the html page that is getting rendered.
While I want some thing like
This is a test message
I get
This is a test <b>message</>
Any help would be awesome.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<script>
function myFunction(){
var children = document.body.childNodes;
for(var len = children.length, child=0; child<len; child++){
if (children[child].nodeType === 3){ // textnode
var highLight = new Array('abcd', 'edge', 'rss feeds');
var contents = children[child].nodeValue;
var output = contents;
for(var i =0;i<highLight.length;i++){
output = delimiter(output, highLight[i]);
}
children[child].nodeValue= output;
}
}
}
function delimiter(input, value) {
return unescape(input.replace(new RegExp('(\\b)(' + value + ')(\\b)','ig'), '$1<b>$2</b>$3'));
}
</script>
</head>
<body>
<img src="http://some.web.site/image.jpg" title="abcd"/>
These words are highlighted: knorex, edge, rss feeds while these words are not: knewedge, abcdef, rss feedssss
<input type ="button" value="Button" onclick = "myFunction()">
</body>
</html>
The problem is that you are putting HTML in to a text node, so it is being evaluated strictly as text. One easy fix would be to simply operate on the innerHTML of the body element, like this:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<script>
function myFunction(){
var highLight = ['abcd', 'edge', 'rss feeds'],
contents = document.body.innerHTML;
for( i = 0; i < highLight.length; i++ ){
contents = delimiter(contents, highLight[i]);
}
document.body.innerHTML = contents;
}
function delimiter(input, value) {
return input.replace(new RegExp('(\\b)(' + value + ')(\\b)','ig'), '$1<b>$2</b>$3');
}
</script>
</head>
<body>
<img src="http://some.web.site/image.jpg" title="abcd"/>
These words are highlighted: knorex, edge, rss feeds while these words are not: knewedge, abcdef, rss feedssss
<input type ="button" value="Button" onclick = "myFunction()">
</body>
</html>
A textNode cannot have child elements so it needs to be replaced, one way;
Replace
children[child].nodeValue = output;
With
var n = document.createElement("span");
n.innerHTML = output;
children[child].parentNode.replaceChild(n, children[child]);

Save variable number of answers to single textbox with Java Script

I am learning JS and I am not yet familiar with internal workings. Can someone point out the error in my thinking?
The basic idea is to ask a complex question, construct the answer with JS (to a CSV syntax) and feed it to a textbox. (From here it will be processed to a db.) Example included below: How many children do you have? What is their names and age?
Perhaps, the new element generated by the first button is not added to the document? How to do this, or how to address the value in it?
How can I make the values submitted to previous lines stick in the event of adding a new line. For example 'Jack' and '10' is written to the first line, the user pressed the add new line, than this information should stay in the first line.
Incorrectly working example: The save button stops working if the code in the loop is added.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<p>How many children do you have? What is their names and age?</p>
<input type="text" id="qchildren" />
<div id="qchildren-answer-wrapper"></div>
<button type="button" onclick="addNew()">Add new entry</button>
<button type="button" onclick="save()">Save</button>
<script>
var lines = 0;
function addNew() {
lines++;
document.getElementById("qchildren-answer-wrapper").innerHTML += 'Gyermek neve:<input type="text" id="qchildrenname' + window.lines + '" /> Gyermek eletkora:<input type="text" id="qchildrenage' + window.lines + '" /><br/>';
}
function save() {
var answer = '';
for (var ii = 0; ii < window.lines; ii++) {
answer += document.getElementById('qchildrenname' + ii.toString()).value.toString() + ',' + document.getElementById('qchildrenage' + ii.toString()).value.toString() + ';';
}
document.getElementById("qchildren").value = answer;
}
< /script>
</body>
</html>
=Below code should work (AddNew function changed):
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<p>How many children do you have? What is their names and age?</p>
<input type="text" id="qchildren" />
<div id="qchildren-answer-wrapper"></div>
<button type="button" onclick="addNew()">Add new entry</button>
<button type="button" onclick="save()">Save</button>
<script>
var lines=0;
function addNew()
{
lines++;
var newElement = document.createElement("span");
newElement.innerHTML = 'Gyermek neve:<input type="text" id="qchildrenname'+window.lines+'" /> Gyermek eletkora:<input type="text" id="qchildrenage'+window.lines+'" /><br/>';
document.getElementById("qchildren-answer-wrapper").appendChild(newElement);
}
function save()
{
var answer='';
for (var ii=1;ii<=window.lines;ii++)
{
answer+=document.getElementById('qchildrenname'+ii.toString()).value.toString()+','+document.getElementById('qchildrenage'+ii.toString()).value.toString()+';';
}
document.getElementById("qchildren").value=answer;
}
</script>
</body>
</html>​
Try code like this:
function addNew()
{
var div = document.createElement('div');
div.innerHTML = 'Gyermek neve:<input type="text" id="qchildrenname'+window.lines+'" /> Gyermek eletkora:<input type="text" id="qchildrenage'+window.lines+'" /><br/>';
document.getElementById("qchildren-answer-wrapper").appendChild(div );
lines++;
}
Demo: http://jsfiddle.net/JByVg/8/
What happens in your case is that all previously created elements are recreated again because element.innerHTML += "some_html" is equal to element.innerHTML = element.innerHTML + "some_html" or, more clear, I suppose, var oldHtml = element.innerHTML;element.innerHTML = ""; element.innerHTML = oldHtml + "some_html"
Browser does not populate value="..." entered by user when you do var oldHtml = element.innerHTML and after += you have old elements recreated without values entered by user. At the same time, appendChild does not recreate old elements.
This example demonstrates how .innerHTML returns only initial HTML (I've added value="test" to your qchildrenname element code)

Categories