I am new to javascript and I am trying to have my button say read or unread when a user clicks on it I've tried adding my readBookfunction to the onclick but I get an error like this, any help would be appreciated
I want it to look like this below and have the button either be read or unread
script.js
class Book {
constructor(title, author, read) {
this.title = title;
this.author = author;
this.read = read;
addBookToLibrary(this);
}
}
let myLibrary = [];
const table = document.getElementById('libraryTable');
let hiddenForm = document.getElementById('hiddenForm')
//toggles the input form opacity and z-index
function showForm() {
hiddenForm.classList.toggle('active')
}
function clearInput() {
inputs = document.getElementsByTagName('input')
for (let i in inputs) {
inputs[i].value = ''
}
}
function createBook() {
new Book(document.getElementById('title').value,
document.getElementById('author').value,
document.getElementById('read').value);
}
const harrypotter = new Book('Harry Potter', 'JK Rowling', 'read')
const stripedpajamas = new Book('The Boy in the Striped pajamas', 'John Boyne', 'read')
const randomBook = new Book('The random book', 'random author', 'read')
function addBookToLibrary(book) {
myLibrary.push(book);
}
function readBook(Book) {
let position = 0;
for (i = 0; i < myLibrary.length; i++) {
if (Book.title == myLibrary[i].title) {
position = i;
}
}
if (myLibrary[position].read == 'read') {
myLibrary[position].read = "unread";
} else {
myLibrary[position].read = "read";
}
return myLibrary[position].read;
}
function displayBooks() {
table.textContent = '';
for (i = 0; i < myLibrary.length; i++) {
let newRow = table.insertRow(i);
newRow.insertCell(0).innerText = myLibrary[i].title;
newRow.insertCell(1).innerText = myLibrary[i].author;
newRow.insertCell(2).innerHTML = `<button onclick='${i}' class='tableButtons' >${myLibrary[i].read}</button>`
newRow.insertCell(2).innerHTML = `<button onclick='removeBook(${i})' class='tableButtons' >Delete</button>`
}
}
function removeBook(index) {
if (index > 1) {
myLibrary.splice(index, index - 1);
} else if (index == 1) {
myLibrary.splice(index, index);
} else if (index == 0) {
myLibrary.shift();
}
}
const displayButton = document.querySelector(".display");
displayButton.addEventListener('click', button => {
displayBooks();
});
Related
I created a basket in JavaScript, it works perfectly except for one thing:
When we add products to the basket, we select a quantity and everything goes well, but if we click again to add the same product, instead of modifying the quantity of the product, the same product is added to the localStorage.
To avoid this problem, I have to search for the product in the localStorage with the Array.find() method, if the product exists, I modify the quantity, otherwise I add it. But I don't know how to do it the right way yet
let basket = JSON.parse(localStorage.getItem('monPanier')) || [];
let wishlist = JSON.parse(localStorage.getItem('myWishList')) || [];
let totalBasket = 0;
let nbrArticles;
let nbrWishlist;
function addBasket()
{
let quantity_cart = $(".input_quantity"+$(this).data("id")).val();
let name_article_cart = $(this).data("name");
let idArticle = parseInt(this.id.replace("add_basket_btn_",""));
let price_cart = $(this).data("price");
let total_price_cart = (quantity_cart * price_cart);
let newBasket = [idArticle,quantity_cart,name_article_cart,price_cart,total_price_cart];
basket.push(newBasket);
saveStorageBasket();
loadStorageBasket();
showBasket();
calculeNbrArticle();
console.log(newBasket);
}
function addWishlist()
{
let name_article_wishlist = $(this).data("name");
let idArticle = parseInt(this.id.replace("add_wishlist_btn_",""));
let price_article_wishlist = $(this).data("price");
let newWishlist = [idArticle,name_article_wishlist,price_article_wishlist];
wishlist.push(newWishlist);
saveStorageWishlist();
loadStorageWishlist();
showWishList();
calculeNbrWishlist();
}
function showBasket() {
//vider le panier
$("#basket").empty();
totalBasket = 0;
for(let i=0; i < basket.length; i++)
{
totalBasket = totalBasket + basket[i][4];
$("#basket").append("<tr><td>"+basket[i][1]+"</td>"
+"<td>"+basket[i][2]+"</td>"
+"<td>"+basket[i][3]+"€</td>"
+"<td>"+basket[i][4]+"€</td>"
+"<td><button data-id='"+i+"' class='btn_cancel_basket'>supprimer</button></td>"
+"</tr>");
}
// installer un event
$("#basket button.btn_cancel_basket").on("click",suppArticleBasket);
$("#totalBasket").text(totalBasket+" €");
}
function suppArticleBasket()
{
let index = $(this).data('id');
console.log(index);
basket.splice(index,1);
saveStorageBasket();
loadStorageBasket();
showBasket();
}
function showWishList()
{
for(let i=0; i < wishlist.length; i++)
{
$("#Wishlist").append("<tr><td>"+wishlist[i][1]+"</td>"
+"<td>"+wishlist[i][2]+"</td>"
+"</tr>");
}
}
function emptyBasket()
{
if(basket == null || basket == 0)
{
console.log("panier = true");
return true;
}else
{
console.log("panier = false");
return false;
}
}
function validateBasket()
{
if(emptyBasket() == false)
{
loadStorageBasket();
basket = JSON.stringify(basket); //js --> json
console.log($.get("index.php","action=appelAjax2&Basket="+basket+"&total="+totalBasket,resetBasket));
}
}
function resetBasket(reponse){
$("#confirmationcmd").html("<p>Commande validée.</p>");
$("#basket").empty();
basket.length = 0;
localStorage.clear();
loadStorageBasket();
showBasket();
totalBasket = 0;
calculeNbrArticle();
}
function resetBasket2(reponse){
$("#confirmationcmd").html("<p>Panier annulé.</p>");
$("#basket").empty();
basket.length = 0;
localStorage.clear();
loadStorageBasket();
showBasket();
totalBasket = 0;
calculeNbrArticle();
}
function resetWishlist(reponse){
$("#confirmationWishlist").html("<p>Wishlist remise à zéro.</p>");
$("#wishlist").empty();
wishlist.length = 0;
localStorage.clear();
loadStorageWishlist();
showWishList();
totalWishlist = 0;
calculeNbrWishlist();
}
function saveStorageWishlist(){
localStorage.setItem("myWishList", JSON.stringify(wishlist));
}
function loadStorageWishlist(){
wishlist = localStorage.getItem("myWishList");
if(wishlist == null)
{
wishlist =[];
}
else
{
wishlist = JSON.parse(wishlist);
}
}
function calculeNbrWishlist()
{
loadStorageWishlist();
nbrWishlist = wishlist.length;
$("#nbrWishlist").text("("+nbrWishlist+")");
}
function saveStorageBasket(){
localStorage.setItem("monPanier", JSON.stringify(basket));
}
function loadStorageBasket(){
basket = localStorage.getItem("monPanier");
if(basket == null)
{
basket =[];
}
else
{
basket = JSON.parse(basket);
}
}
function calculeNbrArticle()
{
loadStorageBasket();
nbrArticles = basket.length;
$("#nbrArticles").text("("+nbrArticles+")");
}
$(function()
{
calculeNbrArticle();
calculeNbrWishlist();
loadStorageBasket();
loadStorageWishlist();
showBasket();
showWishList();
$(".add_basket_btn").on('click',addBasket);
$(".btn_wishlist").on('click',addWishlist);
$("#validateButton").on('click',validateBasket);
$("#resetButton").on('click',resetBasket2);
$("#resetButtonWishlist").on('click',resetWishlist);
});
The basic idea:
push the new basket array if empty
check if the ID is already in the basket array
if so, update the quantity
if not, add the new basket
I have read the following learning resources about:
for loops (w3schools)
find (MDN)
filter (MDN)
According to what I have read in this post Array.find does not work because it finds only the first element. I used the suggested filter option.
The essential part with changes:
function updateQuantity(basket, newBasket, idArticle)
{
// filter: search for articleId in array of arrays
if (basket.filter(({ 1: n }) => n === idArticle)) {
for(i = 0; i < basket.length; i++) {
basket[i][1] += 1;
}
} else {
basket.push(newBasket)
}
}
function addBasket()
{
let quantity_cart = 1
let name_article_cart = "productName"
let idArticle = 1
let price_cart = 10
let total_price_cart = (quantity_cart * price_cart);
let newBasket = [idArticle,quantity_cart,name_article_cart,price_cart,total_price_cart];
if (basket.length === 0) {
basket.push(newBasket)
}
else
{
updateQuantity(basket, newBasket, idArticle)
}
console.log(basket)
}
My complete test code:
let basket = JSON.parse(localStorage.getItem('monPanier')) || [];
let totalBasket = 0;
let nbrArticles;
function updateQuantity(basket, newBasket, idArticle)
{
// filter: search for articleId in array of arrays
if (basket.filter(({ 1: n }) => n === idArticle)) {
for(i = 0; i < basket.length; i++) {
basket[i][1] += 1;
}
} else {
basket.push(newBasket)
}
}
function addBasket()
{
let quantity_cart = 1
let name_article_cart = "productName"
let idArticle = 1
let price_cart = 10
let total_price_cart = (quantity_cart * price_cart);
let newBasket = [idArticle,quantity_cart,name_article_cart,price_cart,total_price_cart];
if (basket.length === 0) {
basket.push(newBasket)
}
else
{
updateQuantity(basket, newBasket, idArticle)
}
console.log(basket)
}
function suppArticleBasket()
{
let index = 1
console.log(index);
basket.splice(index,1);
saveStorageBasket();
loadStorageBasket();
}
function emptyBasket()
{
if(basket == null || basket == 0)
{
return true;
} else
{
return false;
}
}
function saveStorageBasket(){
localStorage.setItem("monPanier", JSON.stringify(basket));
}
function loadStorageBasket(){
basket = localStorage.getItem("monPanier");
if(basket == null)
{
basket =[];
}
else
{
basket = JSON.parse(basket);
}
}
$(function()
{
loadStorageBasket();
$("#add_basket_btn").on('click',addBasket);
});
<button id="add_basket_btn">Add</button>
import './style.css';
let newTask;
const arrowBtn = document.getElementById('arrow');
class Todolist {
constructor(description, completed, index) {
this.description = description;
this.completed = completed;
this.index = index;
}
addtask(dataBase) {
dataBase.push(this);
}
}
arrowBtn.addEventListener('click', () => {
const taskName = document.getElementById('input').value;
let dataBase = JSON.parse(localStorage.getItem('baseData'));
if (dataBase === null) {
dataBase = [];
}
const index = dataBase.length + 1;
newTask = new Todolist(taskName, false, index);
newTask.addtask(dataBase);
localStorage.setItem('baseData', JSON.stringify(dataBase));
document.location.reload();
document.preventDefault();
});
function displaytask() {
const dataBase = JSON.parse(localStorage.getItem('baseData'));
const unsortedList = document.querySelector('.list');
for (let i = 0; i < dataBase.length; i += 1) {
const list = document.createElement('li');
list.id = i + 1;
unsortedList.appendChild(list);
const checkbox = document.createElement('input');
checkbox.classList.add('check');
checkbox.type = 'checkbox';
list.appendChild(checkbox);
let span = document.createElement('input');
span.classList.add('span');
span.type = 'text';
span.value = dataBase[i].description;
list.appendChild(span);
const removeicon = document.createElement('button');
removeicon.classList.add('remove');
removeicon.innerHTML = '<i class="fa-solid fa-trash-can"></i>';
list.appendChild(removeicon);
removeicon.addEventListener('click', () => {
dataBase.splice(i, 1);
list.remove();
for (let i = 0; i < dataBase.length; i += 1) {
dataBase[i].index = i + 1;
}
localStorage.setItem('baseData', JSON.stringify(dataBase));
});
span.addEventListener('change', () => {
if (dataBase[i].description === 'change') {
dataBase[i].description = description.value;
}
localStorage.setItem('baseData', JSON.stringify(dataBase));
})
}
}
displaytask();
I want to change the values of the input from the list of tasks so that these are saved both in the list and in the local storage, I try with 'change' events but is not work.
this is when add to the list:
[https://i.stack.imgur.com/BOT6o.png]
this is when i want to change but is not saved:
[ https://i.stack.imgur.com/ZxoW8.png]
I am not getting the concepts of how pagination works in load more requested data from json api. Even i am getting the data of first page but for remaining pages not getting. If I am using the two api for paging and fetching data but still not getting. Any one help me clear this concepts please..
main-view-model.js
const httpModule = require("tns-core-modules/http");
var observableModule = require("tns-core-modules/data/observable");
function RegisterViewModel() {
var viewModel = observableModule.fromObject({
_sourceDataItems: [],
initDataItems: function () {
//This url for the pagination
var url1 = "https://example.org/api.php?action=query&gcmtitle=Category:xyz&pilimit=max&prop=pageimages&pithumbsize=200&generator=categorymembers&format=json&gcmcontinue=";
httpModule.getJSON(url1).then((r) => {
id = r.continue.gcmcontinue
gcm.push(id)
console.log(gcm)
var pageid = [];
for (var id in r.query.pages) {
pageid.push(id);
}
for (var i = 0; i < pageid.length; i++) {
if (r.query.pages[pageid[i]].thumbnail == null) {
let abc = {
ttt: r.query.pages[pageid[i]].title,
path1: "~/images/xyz.png"
}
this._sourceDataItems.push(abc)
}
else {
let aaa = {
ttt: r.query.pages[pageid[i]].title,
path1: r.query.pages[pageid[i]].thumbnail.source
}
this._sourceDataItems.push(aaa)
}
}
}, (e) => {
});
var gcm = [];
//This url for the fetching the data on scroll
for (var i = 0; i < gcm.length; i++) {
var url2 = "https://example.org/api.php?action=query&gcmtitle=Category:xyz&pilimit=max&prop=pageimages&pithumbsize=200&generator=categorymembers&format=json&gcmcontinue=" + gcm[i];
httpModule.getJSON(url2).then((r) => {
id= r.continue.gcmcontinue)
gcm.push(id)
console.log(r.continue.gcmcontinue)
var pageid = [];
for (var id in r.query.pages) {
pageid.push(id);
}
for (var i = 0; i < pageid.length; i++) {
//placeholder Image
if (r.query.pages[pageid[i]].thumbnail == null) {
let abc = {
ttt: r.query.pages[pageid[i]].title,
path1: "~/images/xyz.png"
}
this._sourceDataItems.push(abc)
}
else {
let aaa = {
ttt: r.query.pages[pageid[i]].title,
path1: r.query.pages[pageid[i]].thumbnail.source
}
this._sourceDataItems.push(aaa)
}
}
}, (e) => {
});
}
},
_DataItems: [],
addMoreItemsFromSource: function (chunkSize) {
let newItems = this._sourceDataItems.splice(0, chunkSize);
this._DataItems = this._DataItems.concat(newItems);
},
onLoadMoreItemsRequested: function (args) {
console.log("---load item called----");
const that = new WeakRef(this);
const listView = args.object;
if (this._sourceDataItems.length > 0) {
setTimeout(function () {
that.get().addMoreItemsFromSource(5);
listView.notifyLoadOnDemandFinished();
}, 100);
args.returnValue = true;
} else {
args.returnValue = false;
}
},
});
return viewModel;
}
exports.RegisterViewModel = RegisterViewModel;
Even loading of the data is working fine for page one. While passing the gcm continue id it wont take that please help me to clear this concept
I am trying to get the female voice accept is "US English" from the Web Speech API.
Below is my code:
var synth = window.speechSynthesis;
var voiceOptioins = synth.getVoices();
var voiceChoice = voiceOptioins[5];
var utterThis = new SpeechSynthesisUtterance(textToSpeech);
utterThis.voice = voiceChoice;
synth.speak(utterThis);
With this code, currently a male voice comes out with super bass. I have tried to change the index in voiceOptioins[<index>]: tried with 0, 5, 10. With all of this indices, only the same male voice comes out.
How do I select a specific voice?
try this code for specific voice
const synth = window.speechSynthesis;
const inputForm = document.querySelector("form");
const inputTxt = document.querySelector(".txt");
const voiceSelect = document.querySelector("select");
const pitch = document.querySelector("#pitch");
const pitchValue = document.querySelector(".pitch-value");
const rate = document.querySelector("#rate");
const rateValue = document.querySelector(".rate-value");
let voices = [];
function populateVoiceList() {
voices = synth.getVoices().sort(function (a, b) {
const aname = a.name.toUpperCase();
const bname = b.name.toUpperCase();
// console.log(aname);
// console.log(bname);
// console.log(a)
if (aname < bname) {
return -1;
} else if (aname == bname) {
return 0;
} else {
return +1;
}
});
const selectedIndex =
voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;
voiceSelect.innerHTML = "";
for (let i = 0; i < voices.length; i++) {
console.log(voices.length);
console.log(voices);
if (i == 6) {
const option = document.createElement("option");
console.log(voices[i])
option.textContent = `${voices[i].name} (${voices[i].lang})`;
// if (voices[0].default) {
// option.textContent += `${voices[0].name} (${voices[0].lang})`;
// }
option.setAttribute("data-lang", voices[6].lang);
option.setAttribute("data-name", voices[6].name);
voiceSelect.appendChild(option);
}
voiceSelect.selectedIndex = selectedIndex;
}
}
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
function speak() {
if (synth.speaking) {
console.error("speechSynthesis.speaking");
return;
}
if (inputTxt.value !== "") {
const utterThis = new SpeechSynthesisUtterance(inputTxt.value);
utterThis.onend = function (event) {
console.log("SpeechSynthesisUtterance.onend");
};
utterThis.onerror = function (event) {
console.error("SpeechSynthesisUtterance.onerror");
};
const selectedOption =
voiceSelect.selectedOptions[0].getAttribute("data-name");
for (let i = 0; i < voices.length; i++) {
if (voices[i].name === selectedOption) {
utterThis.voice = voices[i];
break;
}
}
utterThis.pitch = pitch.value;
utterThis.rate = rate.value;
synth.speak(utterThis);
}
}
inputForm.onsubmit = function (event) {
event.preventDefault();
speak();
inputTxt.blur();
};
pitch.onchange = function () {
pitchValue.textContent = pitch.value;
};
rate.onchange = function () {
rateValue.textContent = rate.value;
};
voiceSelect.onchange = function () {
speak();
};
I wrote my code to search string for keywords and extracting needed data, but I have problems when I'm trying to search with keywords in arrays named: sort, title and artist. When I'm doing it I get an error about potential infinite loop.
var type = ['track','tracks','song','songs','album','albums'];
var artist = ['created by', 'made by'];
var genre = ['genre'];
var limit = ['set limit'];
var title = ['title','name'];
var sort = ['sort by', 'classificate by', 'separate by'];
var sortBy = ['popularity'];
// function changeWordsToNumbers(words) {
// if (msg.numbers[words])
// return msg.numbers[words];
// }
function searchForIndex(instruction, keywords) {
for (i = 0; i < keywords.length; i++) {
let search = instruction.search(keywords[i]);
if (search)
return search;
}
return false;
}
function getSearchResult(wanted) {
var searchResult = {
artist : searchForIndex(wanted, artist),
genre : searchForIndex(wanted, genre),
limit : searchForIndex(wanted, limit),
type : searchForIndex(wanted, type),
title : searchForIndex(wanted, title),
sort : searchForIndex(wanted, sort),
sortBy : searchForIndex(wanted, sortBy)
};
return searchResult;
}
function removeJunkKeyword(searchResult,instruction) {
for(var property in searchResult) {
if(searchResult.hasOwnProperty(property)) {
if(searchResult[property] != - 1) {
instruction = instruction.slice(0, searchResult[property] - 1);
}
}
}
return instruction;
}
function checkExist(searchResult) {
for(var property in searchResult) {
if(searchResult.hasOwnProperty(property)) {
if(searchResult[property] != -1)
return false;
}
}
return true;
}
function findAndCleanQuery(instruction, keywords) {
var exist = instruction.search(keywords);
var result = instruction.slice(exist + keywords.length + 1, instruction.length);
var searchResult = getSearchResult(result);
if (exist != -1) {
if (checkExist(searchResult)) {
return result;
} else {
result = removeJunkKeyword(searchResult,result);
return result;
}
}
return false;
}
function searchFor(instruction, keywords) {
for (i = 0; i < keywords.length; i++) {
let result = findAndCleanQuery(instruction,keywords[i]);
if (result)
return result;
}
return false;
}
function searchForType(instruction) {
for (i = 0; i < type.length; i++) {
let search = instruction.search(type[i])
if(search)
return type[i];
}
return false;
}
function searchForKeywords(instruction) {
msg.artist = searchFor(instruction, artist);
msg.type = searchForType(instruction, type);
msg.genre = searchFor(instruction, genre);
msg.limit = searchFor(instruction, limit);
msg.title = searchFor(instruction, title);
msg.sort = searchFor(instruction, sortreg);
}
var msg = {}
msg.instruction = 'Search for me';
searchForKeywords(msg.instruction);
console.log(msg.artist);
console.log(msg.type);
console.log(msg.genre);
console.log(msg.limit);
console.log(msg.title);
console.log(msg.sort);
Link for code: https://repl.it/J4Mc/9
PS. The object msg is used by node-red to communicate between nodes.
The issue is that you're doing this on several of your loops:
for (i = 0; i < keywords.length; i++) {
...where you should be doing this instead:
for (let i = 0; i < keywords.length; i++) {
Without using let, the variable i is effectively global. Each time you went into a new loop it got reset to 0, so it was never able to increase, which created the infinite loop.
As a side note, you'll also notice sortreg is undefined when it's used on line 98.