I'm using Bootstrap 4 and I have two JS-functions which I want to work together but I can't figure out how..
The first function is for showing the "alt" as caption below images.
The second function is an onClick function which shows the next image by clicking on the image.
My Problem is that when I activate the onClick function and the next image is shown, the "alt" caption doesn't change.
Here is the part of the code:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="row my-row">
<div class="col-md-3 ">
<!--thumbnail container-->
<div class="thumbnailContainer">
</div>
<div class="col-md-9 ">
<!--START MAIN CONTENT-->
<div class="hideMobile">
<div class="d-flex justify-content-center">
<span onclick="this.parentElement.style.display='none'"></span>
<img class="img-fluid img-overlay" id="expandedImg" style="max-height: 80vh;" onClick="nextImage(this)" src="https://images.pexels.com/photos/12233047/pexels-photo-12233047.jpeg?cs=srgb&dl=pexels-chandan-suman-12233047.jpg&fm=jpg">
</div>
<div class="container expandedImgSize d-flex justify-content-center" id="imgtext">
<figcaption style="color: #999999; font-size: 12px;" class="figure-caption">CAPTION
</figcaption>
</div>
</div>
<!--END MAIN CONTENT-->
</div>
<!--col-md-9-->
</div>
</div>
<!--END Wrapper-->
<script type="text/javascript">
// Data
const imagesArr = [{
image: 'https://media.istockphoto.com/photos/stack-of-books-picture-id157482029?b=1&k=20&m=157482029&s=170667a&w=0&h=EVs9M4nx2kPCdIBYMULaSfj75k-wqjEAsaE8GkLwkbw=',
alt: '<br>Test<br>Test1<br>Test1',
},
{
image: 'https://media.istockphoto.com/photos/large-stack-of-papers-on-a-white-background-picture-id178580846?k=20&m=178580846&s=612x612&w=0&h=agODFyEclthiTCyRGMtKoYDGsXRD0GmVpvJnEPhSQws=',
alt: '<br>Test<br>Test2<br>Test2',
},
{
image: 'https://st2.depositphotos.com/2769299/7314/i/450/depositphotos_73146765-stock-photo-a-stack-of-books-on.jpg',
alt: '<br>Test<br>Test3<br>Test3',
},
];
const createImage = (image, alt, index) => {
return `<img src="${image}" alt="${alt}" class="img-thumbnail border-0 img-thumbnail-desktop" onClick="expandingImage(this)" currentimage="${index}"/>`;
};
// Logic
const createImages = (images) => {
let final = '';
for (let i = 0; i < images.length; i++) {
const e = images[i];
final += createImage(e.image, e.alt, i);
}
return final;
}
document.addEventListener("DOMContentLoaded", function() {
console.log('Loaded')
const container = document.querySelector('.thumbnailContainer');
container.innerHTML = createImages(imagesArr)
});
const nextImage = (img) => {
const current = +img.getAttribute('currentimage');
if (current < imagesArr.length - 1) {
img.setAttribute('src', imagesArr[current + 1].image)
img.setAttribute('currentimage', current + 1)
}
}
function expandingImage(imgs) {
const expandImg = document.getElementById("expandedImg");
const imgText = document.getElementById("imgtext");
expandImg.src = imgs.src;
imgText.innerHTML = imgs.alt;
expandImg.setAttribute("currentimage", imgs.getAttribute('currentimage'))
expandImg.parentElement.style.display = "block";
}
</script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous">
</script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous">
</script>
</body>
</html>
Related
I'm trying to display API Pokemon data for Generation 2 Pokemon only (numbers 153 to 251). I'm self-thought through youtube tutorials so I don't know much about JS math, sorry if my terminology is off.
Im trying to get the "const pokemons_number_johtoDex = "20";" number to basically say show "153 to 251".
Any help would be greatly appreciated, Thanks. :)
const poke_container_johtoDex = document.getElementById('poke_containerjohtoDex');
const pokemons_number_johtoDex = 2;
const colors_johtoDex = {
fire: '#FDDFDF',
grass: '#DEFDE0',
electric: '#FCF7DE',
water: '#DEF3FD',
ground: '#f4e7da',
rock: '#d5d5d4',
fairy: '#fceaff',
poison: '#F0D3FF',
bug: '#f8d5a3',
dragon: '#97b3e6',
psychic: '#eaeda1',
flying: '#F5F5F5',
fighting: '#E6E0D4',
normal: '#F5F5F5',
};
const main_types_johtoDex = Object.keys(colors_johtoDex);
const fetchPokemons_johtoDex = async () => {
for (let i = 1; i <= pokemons_number_johtoDex; i++) {
await getPokemon_johtoDex(i);
}
};
const getPokemon_johtoDex = async id => {
const url = `https://pokeapi.co/api/v2/pokemon/${id}/`;
const res = await fetch(url);
const pokemon_johtoDex = await res.json();
createPokemonCard_2(pokemon_johtoDex);
};
function createPokemonCard_2(pokemon_johtoDex) {
const pokemonEl_johtoDex = document.createElement('div');
pokemonEl_johtoDex.classList.add('pokemon_2');
const poke_types_johtoDex = pokemon_johtoDex.types.map(type_johtoDex => type_johtoDex.type.name);
const type = main_types_johtoDex.find(type_johtoDex => poke_types_johtoDex.indexOf(type_johtoDex) > -1);
const color_johtoDex = colors_johtoDex[type];
pokemonEl_johtoDex.style.backgroundColor = color_johtoDex;
const pokeInnerHTML_johtoDex = `
<div class="pokeModelContainer container" data-toggle="modal" data-target="#exampleModal${pokemon_johtoDex.id}">
<div class="pokeiconimage">
<img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vii/icons/${pokemon_johtoDex.id}.png" alt="${name}" />
</div>
<div class="pokecardbody">
<p>No:${pokemon_johtoDex.id} ${name}</p>
</div>
</div>
<div class="modal fade" id="exampleModal${pokemon_johtoDex.id}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="pokemonModalContainer">
<div class="pokemonModalContainerRow">
<div class="pokemonModelImageDiv col">
<img class="pokemonModelImage" src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/${pokemon_johtoDex.id}.png" alt="${name}"/>
</div>
<div class="pokeModeltext col">
<div class="pokemonModelPokemonName">
<h1>${name}</h1>
</div>
<div class="poke-text-block">
<p class="p">Ability: ${pokemon_johtoDex.abilities[0].ability.name}</p>
</div>
<div class="poke-text-block">
<p>
HP: ${pokemon_johtoDex.stats[0].base_stat}<br><br>
Attack: ${pokemon_johtoDex.stats[1].base_stat}<br><br>
Defense: ${pokemon_johtoDex.stats[2].base_stat}<br><br>
Special-Attack: ${pokemon_johtoDex.stats[3].base_stat}<br><br>
Special-Defense: ${pokemon_johtoDex.stats[4].base_stat}<br><br>
Speed: ${pokemon_johtoDex.stats[5].base_stat}</p>
</div>
</div>
<div class="backButton">
<p class="p1">back</p>
</div>
</div>
</div>
</div>
</div>
</div> `;
pokemonEl_johtoDex.innerHTML = pokeInnerHTML_johtoDex;
poke_container_johtoDex.appendChild(pokemonEl_johtoDex);
}
fetchPokemons_johtoDex();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght#400;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<style>
#import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
</style>
<link rel="stylesheet" href="bootstrap.min.css" />
<link rel="stylesheet" href="styles.css" />
<title>Pokemon API</title>
</head>
<body>
<main>
<div class="kanto">
<p>pokemon display kanto</p>
<div id="poke_containerjohtoDex" class="poke-container_johtoDex row" style="display: flex; justify-content: center; "></div>
</div>
<script src="jquery.min.js"></script>
<script src="bootstrap.min.js"></script>
<script src="js.js"></script>
</main>
</body>
If i got you right, you can set the start and end IDs
const start_pokemons_number_johtoDex = 153;
const end_pokemons_number_johtoDex = 251;
And the change the for to go from start to end defined in those const:
for (let i = start_pokemons_number_johtoDex; i <= end_pokemons_number_johtoDex; i++)
This is the complete code:
const poke_container_johtoDex = document.getElementById('poke_containerjohtoDex');
const start_pokemons_number_johtoDex = 153;
const end_pokemons_number_johtoDex = 251;
const colors_johtoDex = {
fire: '#FDDFDF',
grass: '#DEFDE0',
electric: '#FCF7DE',
water: '#DEF3FD',
ground: '#f4e7da',
rock: '#d5d5d4',
fairy: '#fceaff',
poison: '#F0D3FF',
bug: '#f8d5a3',
dragon: '#97b3e6',
psychic: '#eaeda1',
flying: '#F5F5F5',
fighting: '#E6E0D4',
normal: '#F5F5F5',
};
const main_types_johtoDex = Object.keys(colors_johtoDex);
const fetchPokemons_johtoDex = async () => {
for (let i = start_pokemons_number_johtoDex; i <= end_pokemons_number_johtoDex; i++) {
await getPokemon_johtoDex(i);
}
};
const getPokemon_johtoDex = async id => {
const url = `https://pokeapi.co/api/v2/pokemon/${id}/`;
const res = await fetch(url);
const pokemon_johtoDex = await res.json();
createPokemonCard_2(pokemon_johtoDex);
};
function createPokemonCard_2(pokemon_johtoDex) {
const pokemonEl_johtoDex = document.createElement('div');
pokemonEl_johtoDex.classList.add('pokemon_2');
const poke_types_johtoDex = pokemon_johtoDex.types.map(type_johtoDex => type_johtoDex.type.name);
const type = main_types_johtoDex.find(type_johtoDex => poke_types_johtoDex.indexOf(type_johtoDex) > -1);
const color_johtoDex = colors_johtoDex[type];
pokemonEl_johtoDex.style.backgroundColor = color_johtoDex;
const pokeInnerHTML_johtoDex = `
<div class="pokeModelContainer container" data-toggle="modal" data-target="#exampleModal${pokemon_johtoDex.id}">
<div class="pokeiconimage">
<img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vii/icons/${pokemon_johtoDex.id}.png" alt="${name}" />
</div>
<div class="pokecardbody">
<p>No:${pokemon_johtoDex.id} ${name}</p>
</div>
</div>
<div class="modal fade" id="exampleModal${pokemon_johtoDex.id}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="pokemonModalContainer">
<div class="pokemonModalContainerRow">
<div class="pokemonModelImageDiv col">
<img class="pokemonModelImage" src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/${pokemon_johtoDex.id}.png" alt="${name}"/>
</div>
<div class="pokeModeltext col">
<div class="pokemonModelPokemonName">
<h1>${name}</h1>
</div>
<div class="poke-text-block">
<p class="p">Ability: ${pokemon_johtoDex.abilities[0].ability.name}</p>
</div>
<div class="poke-text-block">
<p>
HP: ${pokemon_johtoDex.stats[0].base_stat}<br><br>
Attack: ${pokemon_johtoDex.stats[1].base_stat}<br><br>
Defense: ${pokemon_johtoDex.stats[2].base_stat}<br><br>
Special-Attack: ${pokemon_johtoDex.stats[3].base_stat}<br><br>
Special-Defense: ${pokemon_johtoDex.stats[4].base_stat}<br><br>
Speed: ${pokemon_johtoDex.stats[5].base_stat}</p>
</div>
</div>
<div class="backButton">
<p class="p1">back</p>
</div>
</div>
</div>
</div>
</div>
</div> `;
pokemonEl_johtoDex.innerHTML = pokeInnerHTML_johtoDex;
poke_container_johtoDex.appendChild(pokemonEl_johtoDex);
}
fetchPokemons_johtoDex();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght#400;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<style>
#import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
</style>
<link rel="stylesheet" href="bootstrap.min.css" />
<link rel="stylesheet" href="styles.css" />
<title>Pokemon API</title>
</head>
<body>
<main>
<div class="kanto">
<p>pokemon display kanto</p>
<div id="poke_containerjohtoDex" class="poke-container_johtoDex row" style="display: flex; justify-content: center; "></div>
</div>
<script src="jquery.min.js"></script>
<script src="bootstrap.min.js"></script>
<script src="js.js"></script>
</main>
</body>
I don't know if there is a better way for this API to get a group of IDs in one call, you could look into that in the future.
So I'm using some code from CodePen to make my nagivation buttons as well as my cursor. All of the button creation seems to happen within the JavaScript file, however. I want to add links to each of the buttons to redirect to separate HTML pages. I'm hoping to find a way to do it within the JS file, but all solutions are welcome!
Also, I'm aware this may be a very silly question but I'm still new to web development so bear with me! I'm going to post snippets of the HTML and JS files. I can't include the CSS snippet because the file is much too large.
The website is ryanhursh.xyz for reference of how it's built.
const app = Vue.createApp({
data() {
return {
items: [{ page: "about" }, { page: "works" }, { page: "contact" }],
cursorPosX: 960,
cursorPosY: 540,
cursorFollowActiveBuffer: 16,
buttonHoverFlag: false
};
},
mounted() {
this.cursorPointer = this.$refs.cursorPointer;
this.cursorFollow = this.$refs.cursorFollow;
this.button = document.querySelectorAll(".js-button");
window.addEventListener("mousemove", (e) => {
if (this.buttonHoverFlag === true) {
return;
}
this.mouseMoveCursor(this.cursorPointer, e, 1.0);
this.mouseMoveCursor(this.cursorFollow, e, 1.0);
});
this.onMouseMove();
this.onMouseLeave();
},
methods: {
mouseMoveCursor(element, event, friction) {
this.cursorPosX += (event.clientX - this.cursorPosX) * friction;
this.cursorPosY += (event.clientY - this.cursorPosY) * friction;
element.style.transform = `translate(${
this.cursorPosX - element.clientWidth / 2
}px,${this.cursorPosY - element.clientHeight / 2}px)`;
},
onMouseMove() {
for (let i = 0; i < this.button.length; i++) {
this.button[i].addEventListener("mousemove", (e) => {
this.buttonHoverFlag = true;
this.cursorPointer.style.backgroundColor = "transparent";
this.cursorFollow.style.transform = `translate(${
e.target.getBoundingClientRect().left -
this.cursorFollowActiveBuffer
}px,${
e.target.getBoundingClientRect().top - this.cursorFollowActiveBuffer
}px)`;
this.cursorFollow.style.width =
e.target.getBoundingClientRect().width + "px";
this.cursorFollow.style.height =
e.target.getBoundingClientRect().height + "px";
this.cursorFollow.style.padding =
this.cursorFollowActiveBuffer + "px";
this.cursorFollow.style.borderRadius = 0;
});
}
},
onMouseLeave() {
for (let i = 0; i < this.button.length; i++) {
this.button[i].addEventListener("mouseleave", () => {
this.buttonHoverFlag = false;
this.cursorPointer.style.backgroundColor = "#fff";
this.cursorFollow.style.width = 10 + "px";
this.cursorFollow.style.height = 10 + "px";
this.cursorFollow.style.padding = 32 + "px";
this.cursorFollow.style.borderRadius = "100%";
});
}
}
}
});
app.mount("#app");
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Ryan R. Hursh</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link rel="stylesheet" href="./style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="app">
<header class="header">
<nav class="header__nav">
<ul class="header__list">
<li v-for="item in items" class="header__item"><a class="button js-button">{{ item.page }}</a></li>
</ul>
</nav>
</header>
<div class="cursor">
<div class="cursor__pointer" ref="cursorPointer"></div>
<div class="cursor__follow" ref="cursorFollow"></div>
</div>
</div>
</head>
<!-- content-->
<body>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<link href='https://fonts.googleapis.com/css?family=Lato:300,400,700' rel='stylesheet' type='text/css'>
<!--
<div id='stars'></div>
<div id='stars2'></div>
<div id='stars3'></div>
-->
<div id='title'>
<span>
Ryan R. Hursh
</span>
<br>
<span>
HTML, CSS, JavaScript
</span>
</div>
<!-- end content-->
<!-- embedded scripts -->
<script src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='https://unpkg.com/vue#next'></script>
<script src="./script.js"></script>
</script>
<!-- end scripts -->
</body>
</html>
For buttons that take you to other HTML pages, you can just do:
Html:
<button id="whateveruwant" onclick="whateverfunctionuwant()">text here</button>
The JS is also simple:
function whateverfunctionuwant() {
location.href = "whateverhtmlpageuwant.html"
}
So then the button will direct you to a different HTML page. If Location doesn't work, try Window.href. The Id is for CSS purposes if you wanted to change its appearance and location of it. If you still don't understand, then just go to W3 Schools and search for how to make a button change to another HTML page. (BTW JUST CHANGE THE STUFF THAT I LEFT AS WHATEVER FUNCTION U WANT TO WHAT YOU WANT)
here's the js:
const url = 'https://jsonplaceholder.typicode.com/todos?_limit=3';
async function getDataFromCinemasAPI() {
const response = await fetch(url);
const data = await response.json();
let cardContentForFilling = '<div class="container"><div class="d-flex flex-row"><div class="d-flex flex-col-md-4"><div class="card mb-4 box-shadow"><div class="card-body"><p class="card-text"> </p></div></div></div></div></div>';
for (let i = 0; i < data.length; i++) {
$('.album.py-5').append(cardContentForFilling);
let cards = $('.card-text');
cards.eq(i).html((data[i]["title"]));
}
}
getDataFromCinemasAPI();
here's the html:
<div class="album py-5">
</div>
already tried using flex column/rows but nothing, they stay as a column and not as a row
here's the jsfiddle
You are appending the .container every single time. You have to have them above. Something like this might work:
const url = 'https://jsonplaceholder.typicode.com/todos?_limit=3';
async function getDataFromCinemasAPI() {
const response = await fetch(url);
const data = await response.json();
let cardContentForFilling = '<div class="d-flex flex-col-md-4"><div class="card mb-4 box-shadow"><div class="card-body"><p class="card-text"> </p></div></div></div>';
for (let i = 0; i < data.length; i++) {
$('.append-here').append(cardContentForFilling);
let cards = $('.card-text');
cards.eq(i).html((data[i]["title"]));
}
}
getDataFromCinemasAPI();
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="album py-5">
<div class="container">
<div class="d-flex flex-row append-here">
</div>
</div>
</div>
Preview
please don't use d-flex class bootstrap is already set his col-**-* class with related to flex-box.
show snippet in full-width.
const url = 'https://jsonplaceholder.typicode.com/todos?_limit=3';
async function getDataFromCinemasAPI() {
const response = await fetch(url);
const data = await response.json();
let cardContentForFilling = '<div class="col-md-4 mb-4"><div class="card box-shadow"><div class="card-body"><p class="card-text"></p></div></div></div>';
for (let i = 0; i < data.length; i++) {
$('.append-here').append(cardContentForFilling);
let cards = $('.card-text');
cards.eq(i).html((data[i]["title"]));
}
}
getDataFromCinemasAPI();
.card {
height: 100%;
}
<!DOCTYPE html>
<html lang="pt-br">
<head>
<title>Teste</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</head>
<style>
</style>
<body>
<div class="album py-5">
<div class="container">
<div class="row append-here">
</div>
</div>
</div>
</body>
</html>
I m trying to make a bookmark app in which when i type the name and address of a website they should appear underneath the form when i click submit button.Also when i click the delete button it should remove item not only from UI but also from local storage.And that s the problem.I have no problem deleting them from UI but when i reload the page they keep showing up.I know it s complicated but if someone s interested i would urge them to pay attention to Store class which deals with storage particulary deleteBookmarkFromStorage() method.
document.getElementById("myForm").addEventListener("submit", saveBookmark);
document.querySelector(".col-lg-12").addEventListener("click", function(e) {
const ui = new UI();
ui.deleteItem(e.target);
Store.deleteBookmarkFromStorage(e.target.parentElement);
ui.showAlert("You deleted a bookmark", "alert alert-success");
e.preventDefault();
});
class Bookmark {
constructor(siteName, siteUrl) {
this.siteName = siteName;
this.siteUrl = siteUrl;
}
}
class UI {
constructor() {
this.siteName = document.getElementById("siteName");
this.siteUrl = document.getElementById("siteUrl");
this.bookmarksResults = document.getElementById("bookmarksResults");
}
showAlert(message, className) {
const div = document.createElement("div");
div.appendChild(document.createTextNode(message));
div.className = className;
const container = document.querySelector(".container");
const bookmarkCard = document.getElementById("bookmarkCard");
container.insertBefore(div, bookmarkCard);
setTimeout(() => {
document.querySelector(".alert").remove();
}, 3000);
}
showBookmark(bookmark) {
const div = document.createElement("div");
div.className = "card-body";
div.innerHTML = `
<h3 class="inline-block">${bookmark.siteName}</h3>
<a class="btn btn-primary" target="_blank"
href=${bookmark.siteUrl}>Visit</a>
<a class="btn btn-danger" href="#">Delete</a>
`;
const results = this.bookmarksResults;
results.appendChild(div);
}
clearInput() {
this.siteName.value = "";
this.siteUrl.value = "";
}
deleteItem(target) {
if (target.className === "btn btn-danger") {
target.parentElement.remove();
}
}
}
class Store {
static getBookmarks() {
let bookmarks;
if (localStorage.getItem("bookmarks") === null) {
bookmarks = [];
} else {
bookmarks = JSON.parse(localStorage.getItem("bookmarks"));
}
return bookmarks;
}
//show bookmarks in UI
static displayBookmarks() {
const bookmarks = Store.getBookmarks();
bookmarks.forEach(function(bookmark) {
const ui = new UI();
ui.showBookmark(bookmark);
});
}
//Add bookmark to storage
static addBookmarkToStorage(bookmark) {
const bookmarks = Store.getBookmarks();
bookmarks.push(bookmark);
localStorage.setItem("bookmarks", JSON.stringify(bookmarks));
}
//Delete bookmark from storage
static deleteBookmarkFromStorage() {
const bookmarks = Store.getBookmarks();
bookmarks.forEach(function(bookmark) {
if (bookmark.className === "btn btn-danger") {
bookmarks.splice(index, 1);
}
});
localStorage.setItem("bookmarks", JSON.stringify(bookmarks));
}
}
document.addEventListener("DOMContentLoaded", Store.displayBookmarks);
function saveBookmark(e) {
const siteName = document.getElementById("siteName").value;
const siteUrl = document.getElementById("siteUrl").value;
const bookmark = new Bookmark(siteName, siteUrl);
const ui = new UI();
if (siteName === "" || siteUrl === "") {
ui.showAlert("Please fill in all the fields", "alert alert-danger");
} else {
ui.showBookmark(bookmark);
Store.addBookmarkToStorage(bookmark);
ui.showAlert("You added a new bookmark", "alert alert-success");
ui.clearInput();
}
e.preventDefault();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>My JavaScript App</title>
<!--Bootstrap-->
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous"
/>
</head>
<body>
<div class="container">
<h3 class="mt-3 mb-3 text-muted">Bookmarker</h3>
<hr />
<div class="card card-body pt-5 pb-5 mb-3" id="bookmarkCard">
<h2>Bookmark Your Favorite Sites</h2>
<form id="myForm">
<div class="form-group">
<label>Site Name</label>
<input
type="text"
class="form-control"
id="siteName"
placeholder="Website Name"
/>
</div>
<div class="form-group">
<label>Site URL</label>
<input
type="text"
class="form-control"
id="siteUrl"
placeholder="Website URL"
/>
</div>
<button type="submit" class="btn btn-primary " id="submitButton">
Submit
</button>
</form>
</div>
<div class="row marketing">
<div class="col-lg-12">
<div id="bookmarksResults"></div>
</div>
</div>
<footer class="footer">
<p>© 2019 Bookmarker, Inc.</p>
</footer>
</div>
<script
src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"
></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"
></script>
<script src="build/app.bundle.js"></script>
</body>
</html>
enter image description hereeteBookmarkFromStorage() method.
You can try to remove everything from the local storage before writing back the updated object:
localStorage.clear();
Also, check out how it would work with sessionStorage.
I solved it.
//event listener
Store.deleteBookmarkFromStorage( e.target.previousElementSibling.previousElementSibling.textContent
);
//Class Store
static deleteBookmarkFromStorage(siteName) {
const bookmarks = Store.getBookmarks();
bookmarks.forEach(function(bookmark, index) {
if (bookmark.siteName === siteName) {
bookmarks.splice(index, 1);
}
});
localStorage.setItem("bookmarks", JSON.stringify(bookmarks));
}
Lately I've been having terrible trouble trying to get audio to play on my android device via my phonegap build. I've seen many others have had several issues (mainly pertaining to the correct file path) but none of the solutions I've come across have led to a result. Here is my script for loading and playing the audio:
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<link rel="stylesheet" type="text/css" href="css/index.css" />
<link rel="stylesheet" type="text/css" href="css/style.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<title>Audio</title>
</head>
<body>
<div class="container-fluid">
<div class="col-xs-12 col-md-12">
<div class="s-it">Tap Here</div>
</div>
<div class="row">
<div class="col-xs-4 col-md-4"></div>
<div class="col-xs-4 col-md-4">
<div class="container">
<span style="display:none;" id="vX"></span>
<span style="display:none;" id="vY"></span>
<span style="display:none;" id="vZ"></span>
</div>
<div class="row">
<div class="col-md-12 col-xs-12">
<div id="sbell">
<img src="img/bell.png">
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-xs-12">
<div class="s-text">Test</div>
</div>
<div class="col-md-12 col-xs-12">
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-12"><br><br></div>
</div>
<div class="row">
<div class="col-xs-12 col-md-12"><br><br></div>
</div>
<div class="row">
<div class="col-xs-12 col-md-12">
<div class="well">
<span class="sts">
<img src="img/shake-banner.png">
</span>
</div>
</div>
</div>
</div>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
app.initialize();
</script>
<script type="text/javascript">
var myMedia1 = null;
var myMedia2 = null;
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady () {
var src1 = '';
var src2 = '';
if (device.platform == 'Android') {
src1 = '/android_asset/www/audiomp3/audio1.mp3';
src2 = '/android_asset/www/audiomp3/audio2.mp3';
}
myMedia1 = new Media(src1, onSuccess, onError);
myMedia2 = new Media(sec2, onSuccess, onError);
myMedia1.addEventListener('ended', function () {
setTimeout(function () {
$('#sbell').removeClass('animate-bell');
}, 2000);
setTimeout(function () {
$('.s-text').fadeOut(200);
}, 500);
}, false);
}
function onSuccess () {
alert("Audio Loaded");
}
function onError (e) {
alert(e.message);
}
window.ondevicemotion = function (event) {
var accX = event.accelerationIncludingGravity.x;
var accY = event.accelerationIncludingGravity.y;
var accZ = event.accelerationIncludingGravity.z;
if (accX >= 8 || accX <= -8) {
myMedia2.play();
}
document.getElementById('vX').innerHTML = accX;
document.getElementById('vY').innerHTML = accY;
document.getElementById('vZ').innerHTML = accZ;
};
$(document).ready(function () {
$('#sbell').click(function(event){
$(this).addClass('animate-bell');
$('.s-text').css('color', 'red').fadeIn(300);
myMedia1.play();
});
});
</script>
</body>
#ZyOn (deleted previous comment)
You can use my Media Demo example to find your issue.
Phonegap Demo Apps (core)
The source is on github. It contains sound samples too. I have additional notes, if you need them.
Also, your app.initialize() should be called AFTER the deviceready event.