Is there a way to simplify the below code by using an array? For example, when button 1 (with the index of 0) in the HTML is clicked, could that be used to get a value at index 0 in another array?
function f1() {
document.getElementById("dis").innerHTML = "JoeMae";
}
function f2() {
document.getElementById("dis").innerHTML = "TanakaMae";
}
function f3() {
document.getElementById("dis").innerHTML = "James";
}
function f4() {
document.getElementById("dis").innerHTML = "Deus";
}
<button onclick="f1()">no.1</button>
<button onclick="f2()">no.2</button>
<button onclick="f3()">no.3</button>
<button onclick="f4()">no.4</button>
<p id="dis"></p>
You can simplify without using array:
<button onclick="f('JoeMae')">no.1</button>
<button onclick="f('TanakaMae')">no.2</button>
<button onclick="f('James')">no.3</button>
<button onclick="f('Deus')">no.4</button>
<p id="dis"></p>
function f(str) {
document.getElementById("dis").innerHTML = str;
}
Use another array such that the nth index of that array corresponds to the nth button:
const texts = [
"JoeMae",
"TanakaMae",
"James",
"Deus"
];
const dis = document.getElementById("dis");
document.querySelectorAll('button').forEach((button, i) => {
button.addEventListener('click', () => {
dis.textContent = texts[i];
});
});
<button>no.1</button>
<button>no.2</button>
<button>no.3</button>
<button>no.4</button>
<p id="dis"></p>
Note that unless you're deliberately inserting HTML markup, you should probably use textContent, not innerHTML. (textContent is faster and safer)
Here's an approach that's vanilla JS. I used the dataset API to connect each button to its data, then a single handler to retrieve and display this data.
"use strict";
function byId(id){return document.getElementById(id)}
function newEl(tag){return document.createElement(tag)}
window.addEventListener('load', onLoaded, false);
function onLoaded(evt)
{
var responseArray = ['JoeMae', 'TanakaMae', 'James', 'Deus'];
responseArray.forEach( function(arrElem, elemIndex, arr)
{
var btn = newEl('button');
btn.textContent = `no.${elemIndex+1}`;
btn.dataset.response = arrElem;
btn.addEventListener('click', onClick, false);
document.body.appendChild(btn);
}
);
function onClick(evt)
{
let text = this.dataset.response;
byId('dis').textContent = text;
}
}
<p id='dis'></p>
Here's a slightly cleaner and more flexible example how to implement this type of functionality.
If you are having a lot of rendering functionality like this, I would recommend you to use a library/framework for it, though.
const buttonDefinitions = [
{title: 'no.1', name: 'Monica'},
{title: 'no.2', name: 'Erica'},
{title: 'no.3', name: 'Rita'},
{title: 'no.4', name: 'Tina'}
];
const buttonContainer = document.getElementById('buttonContainer');
const resultContainer = document.getElementById('resultContainer');
for (const buttonDefinition of buttonDefinitions) {
const button = document.createElement('button');
button.innerHTML = buttonDefinition.title;
button.onclick = () => {
resultContainer.innerHTML = buttonDefinition.name;
};
buttonContainer.appendChild(button);
}
<div id="buttonContainer"></div>
<div id="resultContainer"></div>
You can pass the element to the function and access the element data-attributes
In the below example I am passing data-name
function f(element) {
document.getElementById("dis").innerHTML = element.dataset["name"];
}
<button data-name="JoeMae" onclick="f(this)">no.1</button>
<button data-name="TanakaMae" onclick="f(this)">no.2</button>
<button data-name="James" onclick="f(this)">no.3</button>
<button data-name="Deus" onclick="f(this)">no.4</button>
<p id="dis"></p>
Related
I'm having trouble retrieving data from a data-tag attribute on a button that is created by createElement
chatbot.js
const selectServiciosMoviles = document.querySelector('#selectServiciosMoviles')
const addSelect = (select, id, datatag) => {
const selection = document.createElement('button')
selection.classList.add('chatbot__selection')
selection.id = id
selection.setAttribute("data-tag", datatag)
selection.innerHTML = select
messageArea.appendChild(selection)
scrollToBottom(messageArea)
}
selectServiciosMoviles.addEventListener('click', () => {
setTimeout(() => {
addSelect('Portabilidad', 'selectPortabilidad', '{"categoria":"chatbot", "nombre":"chatbot","ubicacion":"home_b2b", "accion":"seleccionar", "etiqueta":"subcategoria_portabilidad"}')
addSelect('Planes Moviles', 'selectMoviles', '{"categoria":"chatbot", "nombre":"chatbot","ubicacion":"home_b2b", "accion":"seleccionar", "etiqueta":"subcategoria_planes_moviles"}')
addSelect('Roaming', 'selectRoaming', '{"categoria":"chatbot", "nombre":"chatbot","ubicacion":"home_b2b", "accion":"seleccionar", "etiqueta":"subcategoria_roaming"}')
addSelect('Seguro Movil', 'selectSeguros', '{"categoria":"chatbot", "nombre":"chatbot","ubicacion":"home_b2b", "accion":"seleccionar", "etiqueta":"subcategoria_seguro_movil"}')
scrollToBottom()
}, 2000)
});
html
<button class="chatbot__selection" id="selectPortabilidad" data-tag="{"categoria":"chatbot", "nombre","chatbot", "ubicacion":"home_b2b", "accion":"seleccionar","etiqueta":"subcategoria_portabilidad"}">Portabilidad</button>
<button class="chatbot__selection" id="selectMoviles" data-tag="{"categoria":"chatbot", "nombre","chatbot", "ubicacion":"home_b2b", "accion":"seleccionar","etiqueta":"subcategoria_portabilidad"}">Planes Moviles</button>
<button class="chatbot__selection" id="selectRoaming" data-tag="{"categoria":"chatbot", "nombre","chatbot", "ubicacion":"home_b2b", "accion":"seleccionar","etiqueta":"subcategoria_portabilidad"}">Roaming</button>
<button class="chatbot__selection" id="selectSeguros" data-tag="{"categoria":"chatbot", "nombre","chatbot", "ubicacion":"home_b2b", "accion":"seleccionar","etiqueta":"subcategoria_portabilidad"}">Seguro Movil</button>
libreria.js
var tagItems = document.querySelectorAll('[data-tag]')
tagItems.forEach(function (e) {
e.addEventListener('click', function (e) {
if(e.target.dataset.tag != undefined){
var data = JSON.parse(e.target.dataset.tag)
console.log(data)
}
})
})
the problem when seeing the console nothing appears to me, the data-tag of the button does not rescue me. please i need help, thanks
I am stuck on this problem. I am coding a task platform app. Whenever I try to save, the task clones itself. After each "Save Changes," there are more and more clones. I have rewritten the code so many times. But still, I am not successful. Please help me to find the error.
$("#taskSave").click(() => {
const task = {
id: Date.now(),
imageUrl: $("#imageInput").val(),
title: $("#titleInput").val(),
description: $("#descriptionInput").val(),
type: $("#typeInput").val(),
};
$("#overlay").hide();
todos.push(task);
saveStorage(todos);
// reset input values
$("#imageInput").val("");
$("#titleInput").val("");
$("#descriptionInput").val("");
$("#typeInput").val("");
});
function saveStorage(todos) {
localStorage.setItem("todos", JSON.stringify(todos));
display(todos);
};
function display(todos) {
$("#taskBoard").innerHTML = "";
// .html("");
todos.forEach(item => {
let c = document.createElement("div");
c.setAttribute("class", "card");
c.setAttribute('id', item.id);
c.innerHTML = `
<div class="cardTop">
<div class="binContainer">
<div class="binImage"></div>
</div>
</div>
<img src="${item.imageUrl}" alt="task image">
<h2>${item.title}<h2>
<p>${item.description}</p>
<div class="cardType">${item.type}</div>
`;
$("#taskBoard").append(c);
// end
});
};
I've created a minimal working example, and the problem is in the cleanup of the HTML. You cannot use innerHTML on the JQuery object, or you use its html function or you need to retrieve the javascript object with $("#taskBoard")[0].
// You can use:
$("#taskBoard").html("");
// or
// document.getElementById("taskBoard").innerHTML = "";
// or
// $("#taskBoard")[0].innerHTML = "";
// But not:
// $("#taskBoard").innerHTML = "";
The working example here on JSFiddle (on SO dont work localStorage)
let todos = [];
$("#taskSave").click(() => {
const task = {
id: Date.now()
};
todos.push(task);
saveStorage(todos);
});
function saveStorage(todos) {
localStorage.setItem("todos", JSON.stringify(todos));
display(todos);
console.log(todos);
};
function display(todos) {
$("#taskBoard").html("");
// or
// document.getElementById("taskBoard").innerHTML = "";
// or
// $("#taskBoard")[0].innerHTML = "";
// But not
// $("#taskBoard").innerHTML = "";
todos.forEach(item => {
let c = document.createElement("div");
c.innerHTML = `
<p>${item.id}</p>
`;
$("#taskBoard").append(c);
});
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="taskSave">
SAVE
</button>
<div id="taskBoard">
</div>
I have a list of user cards. That card contains add and remove button.
I want to remove that card from list of card when I click at remove button.
Code is similar to following:
// function to generate card
function generateUserCard(id) {
return `
<div class="user-card" id="${id}">
<button data-id="${id}" class="add" >Add</button>
<button data-id="${id}" class="remove" >Remove</button>
</div>
`;
}
// function to generate list of user
function generateUsers(users) {
const userGrid = $("#user-grid");
for(let user of users) {
const userCard = generateUserCard(user.id);
userGrid.append(userCard);
// adding event listeners
$(`[data-id=${user.id}]`).on("click", function() {
// I did something like this
(`#${user.id}`).remove(); // But this didn't work
})
}
}
Please help!
There are several issues in the logic used in your click event callback:
The variable id is not accessible in the callback. A quick fix will be to fix the reference so that you are using user.id in the selector instead. Also, you can simply remove it by ID without needing to search for it inside its parent element, since it is unique.
Your selector [data-id]=${user.id} is syntacically incorrect. I suppose you meant [data-id=${user.id}]
You should be using .remove() to remove a node
A quick fix will look like this:
$(`button[data-id=${user.id}].remove`).on("click", function() {
$(`#${user.id}`).remove();
});
See proof-of-concept below:
function generateUserCard(id) {
return `
<div class="user-card" id="${id}">
User ID: ${id}
<button data-id="${id}" class="add" >Add</button>
<button data-id="${id}" class="remove" >Remove</button>
</div>
`;
}
function generateUsers(users) {
const userGrid = $("#user-grid");
for (let user of users) {
const userCard = generateUserCard(user.id);
userGrid.append(userCard);
$(`button[data-id=${user.id}].remove`).on("click", function() {
$(`#${user.id}`).remove();
})
}
}
// For demo only
let i = 0;
$('#btn').on('click', function() {
const userArray = [];
for (let j = 0; j < 3; j++) {
i++;
userArray.push({ id: i });
}
generateUsers(userArray);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn">Generate users</button>
<div id="user-grid"></div>
However, an improvement to your code will be to avoid adding new click event listeners to all your newly appended elements. You can simply listen to the click event bubbling up to a parent that is already present at runtime (e.g. #user-grid), and you can bind it outside of your generateUsers function:
$('#user-grid').on('click', 'button.add, button.remove', function() {
const id = $(this).attr('data-id');
$(`#${id}`).remove();
});
See proof-of-concept below:
function generateUserCard(id) {
return `
<div class="user-card" id="${id}">
User ID: ${id}
<button data-id="${id}" class="add" >Add</button>
<button data-id="${id}" class="remove" >Remove</button>
</div>
`;
}
function generateUsers(users) {
const userGrid = $("#user-grid");
for (let user of users) {
const userCard = generateUserCard(user.id);
userGrid.append(userCard);
}
}
// Listen to event bubbling instead!
$('#user-grid').on('click', 'button.remove', function() {
const id = $(this).attr('data-id');
$(`#${id}`).remove();
});
// For demo only
let i = 0;
$('#btn').on('click', function() {
const userArray = [];
for (let j = 0; j < 3; j++) {
i++;
userArray.push({
id: i
});
}
generateUsers(userArray);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn">Generate users</button>
<div id="user-grid"></div>
I am new to JavaScript and kind of stuck at this place
function onView(data){
var item_size = data;
return item_size;
}
I have this function with parameter passing through HTML input, i want to use return of this function in another function
function onRegisterInput(){
var y= onView(data);
}
onRegisterInput is called onclick Button, i want to take return value of onView function as var y.
How can i do this ??
Everytime i click button onRegisterInput() function is called but my debugger shows data is undefined. Please help. Thanks in advance.
As you can see in onView, it takes data as function parameter, however you don't give it any parameter in your call var y= onView();. From my understanding, onView get's triggered when a button is clicked, so I'd suggest you save your value in a global variable so you can use it across functions
There are 2 ways for you to get the data in your button click callback.
Get data from the DOM
There are different ways to keep data inside the DOM, but data-* attributes are popular:
function testMe(event, button) {
const magicNumber = button.getAttribute('data-magic-number');
document.getElementById('result1').innerHTML = magicNumber;
}
function testMe2(event, button) {
const magicNumber = document.getElementById('magic2').getAttribute('data-magic-number');
document.getElementById('result2').innerHTML = magicNumber;
}
.test {
padding: 4px;
}
<div class="test">
<button id="button1" data-magic-number="123456789" onclick="testMe(event, this)">Button 123456789</button>
<div id="result1"></div>
</div>
<div class="test">
<span data-magic-number="987654321" id="magic2">Click this: </span><button id="button2" onclick="testMe2()">Button 987654321</button>
<div id="result2"></div>
</div>
Another option is to keep data inside the JS
let myMagicNumber = 1;
let resultDiv = document.getElementById('result');
function showNumber() {
resultDiv.innerText = myMagicNumber;
}
function incNumber() {
myMagicNumber++;
showNumber();
}
function decNumber() {
myMagicNumber--;
showNumber();
}
<div>
<button onclick="showNumber()">Show</button>
<button onclick="incNumber()">+1</button>
<button onclick="decNumber()">-1</button>
</div>
<div id="result">
</div>
Let's return to your example
function onView(data) {
// Some data processing
// We will return data length for example
return (typeof data === 'string' ? data.length : 0);
}
function onRegisterInput() {
// Button click
let data = document.getElementById('name').value;
if (data != '') {
var y = onView(data);
document.getElementById('result').innerText = 'Name: ' + data + ', length: ' + y;
} else {
document.getElementById('result').innerText = 'Enter your name';
}
}
<div>
<label>Name: <input type="text" id="name"/></label>
<button onclick="onRegisterInput()">Register</button>
</div>
<div id="result"></div>
function setParagraph(paraList) {
$.each(paraList, function (i, field) {
var pElement = document.createElement('p');
$(pElement).text(field);
//a line that combines the p elements like so:
//<p>First para</p>
//<p>Second para</p>
});
return //all elements for append;
}
I am trying to write code with minimum number of lines to return a "collection" of p elements that needs to be appended to the following div:
$("#somediv").append(setParagraph(jsonValue));
To produce:
<div id="somediv">
<p>First para</p>
<p>Second para</p>
</div>
The method setParagraph is passed json string with collection of string items that are translated into p elements in the method.
I have tried pushing the elements into an array but I don't think that is the right way to go.
Also, I do not wish to use string concatenation in the loop to produce the desired results, unless of course that is the only best way to handle it.
EDIT:
The below works but as I said I am looking for some other solution besides array:
function setParagraph(paraList) {
var arrElements = [];
$.each(paraList, function (i, field) {
var $pElement = $("<p/>").text(field);
arrElements.push($pElement);
});
return arrElements;
}
var jsonValue = ["First para","Second para"];
$("#somediv").append(setParagraph(jsonValue));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="somediv">
</div>
Shorter
const par = ["one", "two", "three"]
$("#somediv").html(par.map(p => $("<p>", { text: p })))
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="somediv"></div>
You can use $.map(..) for that, here is an example:
function setParagraph(paraList) {
return $.map(paraList, function(item) {
return $("<p>", {
text: item
});
});
}
$("#somediv").append(setParagraph(["one", "two", "three"]));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="somediv"></div>
I've created a simple fiddle example that I think would suit your needs. It works in a different way, a little bit at least, but with a bit of changing you'd get your desired result.
Here's the fiddle: https://jsfiddle.net/fkoLn4v9/
Here's the code:
// index.js
const paragraphsCollection = [
{
tag: 'p',
content: 'This is the first parargraph',
},
{
tag: 'p',
content: 'This is the second paragraph',
},
];
const setParagraph = (parentElem, contentData) => {
contentData.forEach(({ tag, content }) => {
const domElem = document.createElement(tag);
domElem.innerText = content;
parentElem.appendChild(domElem);
});
};
const divElem = document.querySelector('.parentDiv');
setParagraph(divElem, paragraphsCollection);
HTML:
<div class="parentDiv"></div>