I have two different functions and I created a third function which I use to display some pieces of information. What I am trying to do is: I want to display photographerPrice which is inside of the photographerProfil function and the sum of all the likes which is inside of the photographerWork function, those two elements I want to display inside my third function likesAndPrice.
I tried to call the function likesAndPrice inside two of the functions photographerProfil and photographerWork using two arguments and two parameters: it doesn't work, it only works when I use one single parameter either for likes or the price but not both. How can I display the two of them Price and Likes in one place ?
The result I want:
photographerProfil Function code
function photographerProfil(JsonData){
const id = window.location.search.split('id=')[1];
const photographers = !id ? JsonData.photographers : JsonData.photographers.filter(photographer => photographer.id == id);
photographers.forEach(element => {
const domDiv = document.getElementById('photographer-container');
const newDiv = document.createElement('div');
const photographerPrice = element.price;
const profilTemplate = `
<div class="profil-container">
<h2>${element.name}</h2>
<p>${element.city}, ${element.country}</p>
<p class="tagline">${element.tagline}</p>
<p>${element.tags.map(tag => `<button class='tags'>#${tag}</button>`).join(" ")}</p>
<button id="test">Contactez-moi</button>
<div class="photoBox">
<img src="${element.portrait}" alt="photo">
</div>
</div>
`
newDiv.innerHTML = profilTemplate;
domDiv.appendChild(newDiv);
showModal(); // function invoked here
photographerWork(JsonData, element) // function invoked here
})
}
photographerWork Function code
function photographerWork(JsonData, homeElement){
let sum = 0;
const homeElt = homeElement.id;
JsonData.media.forEach(element => {
if(homeElt == element.photographerId){
const domDiv = document.getElementById('photographer-work');
const newDiv = document.createElement("div");
sum += element.likes;
const workTemplate = `
<div class="photo-box">
<div class="photo">
${videoOrImage(element.image, element.video, element)}
</div>
<div class="text">
<p> ${element.tags}<b>${element.price} €   ${element.likes} <i class="fas fa-heart"></i></b></p>
</div>
</div>
`
newDiv.innerHTML = workTemplate;
domDiv.appendChild(newDiv);
}
})
likesAndPrice(sum) // function invoked here
}
And the Function in which I want to display the Likes and Price
//total likes and price
function likesAndPrice(sum){
const domDiv = document.getElementById('photographer-work');
const newDiv = document.createElement("div");
const likesAndPriceTemplate = `
<span>${sum} <i class="fas fa-heart"></i></span>
<span></span>
`
newDiv.classList.add('likesAndPriceContainer')
newDiv.innerHTML = likesAndPriceTemplate;
domDiv.appendChild(newDiv)
}
Assuming you can also call likesAndPrice() in your photographerProfil function
Inside photographerWork at the last line you can return the local sum variable
return sum;
Now when you invoke the function at photographerProfil it returns the sum
let sum = photographerWork(JsonData, element) // function invoked here
Now you have your sum and the photographerPrice both in your photographerprofil function available this means you can call here the likesAndPrice function.
likesAndPrice(sum, photographerPrice) // function invoked here
Note: you have to update the signature where you define the function likeAndPrice() and add another parameter to it
function likesAndPrice(sum, <param>){
Related
i have fetchTeam(teamName) function which gets an array of players and displays them in HTML. and another function that takes a player name as a parameter and displays the player stats. Something like this....
let result = document.getElementById("result");
let teamName;
const fetchTeam = async (teamName) => {
teamName = document.getElementById("teamName").value;
const response = await fetch(`http://localhost:3000/${teamName}`);
const data = await response.json();
let team = data.teamStats;
let players = data.playerStats;
const teamName = team[0].Name;
const logo = team[0].Logo;
const WL = team[0].WL;
result.innerHTML = `
<br><div class="top">
<h3>${teamName}</h3>
<h4>Win / Loss: ${WL}</h4>
<img src=${logo}></div>
<div class="flex-container">
<div class="flex-child">
<button class='name' onclick="fetchPlayer("${players[0][0].Player}")> ${players[0][0].Player} </button> ...
`
That all works fine except the onclick fetchPlayer function at the bottom.... Heres the code for that:
const results = document.getElementById("results");
const fetchPlayer = async (player) => {
const response = await fetch(`https://get-player.herokuapp.com/${player}`);
const data = await response.json();
results.innerHTML = `
<br>
<div class="layout">
<div class="child"><img src="${data.sprite}[0]"><br>${data.mons[0]}</div>
`
As you can see, i want to display the team members and then clicking on a member name will show their stats.
edit: format
There are several issues in your code.
First, you redeclare teamName in your fetchTeam function. That cannot work.
const fetchTeam = async (teamName) => {
teamName = document.getElementById("teamName").value;
...
const teamName = team[0].Name;
}
Second, your button syntax is incorrect :
<button class='name' onclick="fetchPlayer("${players[0][0].Player}")>
should be
<button class='name' onclick="fetchPlayer('${players[0][0].Player}')">
Third, as pointed out in this answer, in your fetchPlayer function
<img src="${data.sprite}[0]"> should be <img src="${data.sprite[0]}">
In the fetchPlayer function,
Change <img src="${data.sprite}[0]"> to <img src="${data.sprite[0]}">
I have 2 divs with same class but different textContent
I want to extracts its value using eventListners and pass it as a argument to another function
Html Code
<div class = "seasonDeatils__container">
<p class = "seasonYear ">2020</p>
</div>
<div class = "seasonDeatils__container">
<p class = "seasonYear ">2019</p>
</div>
JavaScript Code I tried
var season;
const getSeasonYear = document.querySelectorAll('.seasonDeatils__container');
getSeasonYear.forEach((el)=>{
el.addEventListener('click', ()=>{
season = el.firstElementChild.textContent;
})
})
//I now want to access the 'season' value elsewhere in the code
Just pass the value of season as an argument from inside your click listener function itself to a function elsewhere in your code as follows:
var season;
const getSeasonYear = document.querySelectorAll('.seasonDeatils__container');
getSeasonYear.forEach((el)=>{
el.addEventListener('click', ()=>{
season = el.firstElementChild.textContent;
someOtherFunction(season);
})
})
someOtherFunction = x => {
console.log(x);
alert(x);
}
<div class = "seasonDeatils__container">
<p class = "seasonYear ">2020</p>
</div>
<div class = "seasonDeatils__container">
<p class = "seasonYear ">2019</p>
</div>
I am trying to pass two variables one is having integer and other is having some string,say i want to pass id,name
<div class='redstatus' onclick='redStatus("+Id+","+name+")'><span class='countspan''>"+red_count+"</span></div>
In the above code in onclick function if i pass only id <div class='redstatus' onclick='redStatus("+Id+")'><span class='countspan''>"+red_count+"</span></div> it is working fine.
I want to send one more parameter name along with id separated by comma
<div class='redstatus' onclick='redStatus("+Id+","+name+")'><span class='countspan''>"+red_count+"</span></div>
it is not working.I need help on this.
for(var i in appData ){
console.log("Data"+JSON.stringify(appData));
for(j in appData.LOB){
var LOBId = appData.LOB[j].LOBID;
LOBName = appData.LOB[j].LOBName;
var LOBRef = appData.LOB[j].LOBRef;
var LOBNameRef = appData.LOB[j].LOBNameRef;
//console.log("LOBId"+LOBId+"LOBName"+LOBName);
$(".left_div").append("<div class='left_lob_name'>"+LOBName+"</div>");
streamInRed = [];
streamInAmber = [];
streamInGreen = [];
currentItemRed = [LOBId];
currentItemAmber = [LOBId];
currentItemGreen = [LOBId];
//$("."+LOBNameRef+"").append("<div id="+LOBId+" style='height:74vh;overflow-y:auto;'><table class='table table-bordered' ><thead><tr><th>StreamName</th><th>BusinessSLA Description</th><th>Status</th><th>Business SLA</th><th>Forecast Completion Time</th><th>Actual Completion Time</th><th>JobName</th></tr></thead><tbody class='"+LOBRef+"'></tbody></table></div>");
for(var k in appData.LOB[j].Streams.Stream){
//console.log("Streams"+JSON.stringify(appData.LOB[j].Streams.Stream));
var streamId = appData.LOB[j].Streams.Stream[k].streamId;
var streamName = appData.LOB[j].Streams.Stream[k].streamName;
var Status = appData.LOB[j].Streams.Stream[k].Status;
var jobName = appData.LOB[j].Streams.Stream[k].JobName;
var BSD= appData.LOB[j].Streams.Stream[k].BusinessSLADescrition;
var BSLA = appData.LOB[j].Streams.Stream[k].BusinessSLA;
var FCT = appData.LOB[j].Streams.Stream[k].ForecastCompletionTime;
var ACT = appData.LOB[j].Streams.Stream[k].ActualCompletionTime;
var RAGStatus = appData.LOB[j].Streams.Stream[k].RAGStatus;
if(Status == "red"){
//$("."+LOBName+"").append("<div class='streamcolor_red test' data-name='1'>"+streamName+"</div>");
//$("."+LOBRef+"").append("<tr class='test' data-name='1'><td style='background-color:#f3180d;color:#fff;'>"+streamName+"</td><td>"+BSD+"</td><td>"+RAGStatus+"</td><td>"+BSLA+"</td><td>"+FCT+"</td><td>"+ACT+"</td><td>"+jobName+"</td></tr>");
red_count = red_count+1;
currentItemRed = [streamName,BSD,RAGStatus,BSLA,FCT,ACT,jobName];
streamInRed.push(currentItemRed);
//redStatus();
//console.log("streamInRed"+streamInRed);
}else if(Status == "amber"){
//$("."+LOBRef+"").append("<tr class='test' data-name='2'><td style='background-color:rgba(243, 168, 15, 0.9215686274509803);color:#fff;'>"+streamName+"</td><td>"+BSD+"</td><td>"+RAGStatus+"</td><td>"+BSLA+"</td><td>"+FCT+"</td><td>"+ACT+"</td><td>"+jobName+"</td></tr>");
//$("."+LOBName+"").append("<div class='streamcolor_amber test' data-name='2'>"+streamName+"</div>");
amber_count = amber_count+1;
currentItemAmber = [streamName,BSD,RAGStatus,BSLA,FCT,ACT,jobName];
streamInAmber.push(currentItemAmber);
}else {
//$("."+LOBRef+"").append("<tr class='test' data-name='3'><td style='background-color:green;color:#fff;'>"+streamName+"</td><td>"+BSD+"</td><td>"+RAGStatus+"</td><td>"+BSLA+"</td><td>"+FCT+"</td><td>"+ACT+"</td><td>"+jobName+"</td></tr>");
//$("."+LOBName+"").append("<div class='streamcolor_green test' data-name='3'>"+streamName+"</div>");
green_count = green_count+1;
currentItemGreen=[streamName,BSD,RAGStatus,BSLA,FCT,ACT,jobName];
streamInGreen.push(currentItemGreen);
}
//console.log("streamId"+streamId+"streamName"+streamName+"Status"+Status);
}
console.log("LOBId",LOBId);
console.log("sep_symbol",sep_symbol);
console.log("syb",syb);
console.log("LOBNameRef",LOBNameRef);
var tempvar = "'"+LOBNameRef+"'";
console.log("tempvar"+LOBId +sep_symbol +tempvar);
$("<div style='text-align:center;height:5vh;margin:2vw;'> <div class='redstatus' onclick='redStatus("+LOBId+","+LOBNameRef+")'><span class='countspan''>"+red_count+"</span></div> <div class='amberstatus' onclick='amberStatus("+LOBId+")'><span class='countspan'>"+amber_count+"</span></div> <div class='greenstatus' onclick='greenStatus("+LOBId+")'><span class='countspan'>"+green_count+"</span></div></div>").appendTo(".right_div");
red_count = 0;
amber_count = 0;
green_count = 0;
//var Streams = appData.LOB[j].Streams;
//console.log("Before"+$wrapper);
//var $wrapper = $('.'+LOBRef+'');
//console.log("after"+$wrapper);
//$wrapper.find('.test').sort(function (a, b) {
/// return +a.dataset.name - +b.dataset.name;
//})
//.appendTo( $wrapper );
}
}
i have added the code for your reference
The problem is with the line
$("<div style='text-align:center;height:5vh;margin:2vw;'> <div class='redstatus' onclick='redStatus("+LOBId+","+LOBNameRef+")'><span class='countspan''>"+red_count+"</span></div> <div class='amberstatus' onclick='amberStatus("+LOBId+")'><span class='countspan'>"+amber_count+"</span></div> <div class='greenstatus' onclick='greenStatus("+LOBId+")'><span class='countspan'>"+green_count+"</span></div></div>").appendTo(".right_div");
which, more prettily, and without the inline handlers, can be constructed like:
const htmlStr = `
<div style='text-align:center;height:5vh;margin:2vw;'>
<div class='redstatus'><span class='countspan'>${red_count}</span></div>
<div class='amberstatus'><span class='countspan'>${amber_count}</span></div>
<div class='greenstatus'><span class='countspan'>${green_count}</span></div>
</div>
`;
You can pass the HTML string to jQuery to get a jQuery collection, then select the inner divs and add a listener to each:
const $row = $(htmlStr);
$row.find('.redstatus').on('click', () => redStatus(LOBId, LOBNameRef));
$row.find('.amberstatus').on('click', () => amberStatus(LOBId, LOBNameRef));
$row.find('.greenstatus').on('click', () => greenStatus(LOBId, LOBNameRef));
$row.appendTo(".right_div");
(or pass whatever parameters you want to the status functions - no quote escaping required!)
Make sure the LOBIds and LOBNameRefs don't reassign themselves in other iterations of the loop - declare them with const, eg:
const LOBId = appData.LOB[j].LOBID;
const LOBName = appData.LOB[j].LOBName;
const LOBRef = appData.LOB[j].LOBRef;
so they're scoped to the block, not to the function.
(It would also probably be good to have just a single <color>Status function, rather than three separate standalone functions (which probably all do something somewhat similar) - too much repetition should be avoided)
You want to concatenate two parameters passed to a function, do not enclose variables in single or double quotes, it should be as :onclick="redStatus(Id,name)"
function redStatus(Id,name){
var result = Id+'_'+name;
document.getElementsByClassName('countspan')[0].innerText = result;
}
<!DOCTYPE html>
<html>
<head>
<title>Append Two Params</title>
</head>
<body>
<div onclick="redStatus(1,'name')">Append Two Params</div>
<span class='countspan'></span>
</body>
</html>
In vanilla JavaScript how can I bind an element to an object so that if a child element of the object has a value I can update the object with it? Need to be compatible with IE10+ and all other browsers.
With a button I am dynamically adding an element (createElement()) containing a form input. When the element is created it also creates an object that should also be the element so I can update the object with the input value on change.
I then store each new object in an array.
The issue I am having is connecting the input value with the correct object. I tried looping through the array hoping to update each object in turn with the current input value of the event target but couldn't succeed. I tried registering the element (deprecated) and various other things but I cannot quite workout how to link the input to the container object (lineObject).
I could really use some help solving this problem and understanding how to bind an element to an object in the way I need.
//lineNumber *** //
let lineNumber = document.querySelectorAll('.lineNumber');
let numberOfLines = lineNumber.length;
//first instance of input element
let lineText = document.querySelector('.lineText');
//first input value of element
let lineTextValue = document.querySelector('input[name="lineText"]').value;
//create initial lineObject for first line
let lastLine = lineNumber[numberOfLines - 1];
let lineContainer;
//lineNumber object constructor
function LineObject(lineText, writable) {
//set properties
this.lineText = lineText;
this.writable = writable;
}
//new object at new lineNumber element, set values
let lineObject = new LineObject(lineTextValue, true);
//create array containing initial line object
let lineArray = [lineObject];
//line functions
(function lineGeneration(){
//add or remove lines
document.addEventListener('click', function(e) {
//this
let self = e.target;
// has class .addLine
if (hasClass(self, 'addLine')) {
//call function to get variables
insertLineHTML();
//clone new line after the last line\
self.parentElement.parentElement.parentElement.parentElement.parentElement.appendChild(lineObject.cloneNode(true));
//lineNumber input location
let newlineTextInput = self.parentElement.parentElement.parentElement.parentElement.nextElementSibling.querySelector('input[name="lineText"]');
//input value of new element
let lineTextValue = newlineTextInput.value;//normally "" when created unless placeholder text
//new object at new lineNumber element
lineObject = new LineObject(lineTextValue, true);
//add new object to lineArray
lineArray.push(lineObject);
refreshLineNodeList();
}
});
//combine accordion / refresh
function refreshLineNodeList(){
//refresh number of elements in nodelist
lineNumber = document.querySelectorAll('.lineNumber');
//get new length
numberOfLines = lineNumber.length;
}
//line html and vars
function insertLineHTML(){
lineObject = document.createElement('div');
lineObject.setAttribute('class', 'lineNumber');
lineObject.innerHTML = `
<div class="accordion-title">
<h3>Line 2</h3>
</div>
<div class="input-section">
<div class="input-row">
<div class="input-container">
<label>Line 2 :</label>
<input type="text" name="lineText" value="" class="lineText">
</div>
<div class="input-row">
<div class="button-container">
<div class="warning"></div>
<button class="addLine">Add Another Line</button>
</div>
</div>
</div>`;
console.log(lineNumber);
}
})();
//lineText addEventListener update object value
document.addEventListener('keyup', function(e) {
let self = e.target;//input field
let lineTextValue = self.value;
// has class .lineText
if (hasClass(self, 'lineText')) {
//for each lineObject in LineArray
//lineArray.forEach(function(arrayObject) {
//update lineObject HTMLelement.prototype
Object.defineProperty(lineObject, 'lineText', {
//update object value to event target value
get: function() {
return this.lineTextValue;//how can I get the right lineObject object from the array when I update the input
},
set: function(lineTextValue) {
this.lineText = lineTextValue;//how can I aet the right lineObject object in the array when I update the input
}
});
//debugging
//console.log('objectProperty = ' + arrayObject.lineText);
console.log('this.lineText = ' + this.lineText);
console.log('Object.entries(lineObject) - ' + Object.entries(lineObject));
//console.log('lineObject.lineText = '+ lineObject.lineText);
//console.log('lineTextValue = '+ lineTextValue);
//});
};
});
let button = document.getElementById('test');
button.addEventListener( "click", testFunction );
function testFunction(){
button.addEventListener( "click", testFunction );
//console.log('Object.keys(lineObject) - '+ Object.keys(lineObject));
//console.log('Reflect.ownKeys(lineObject) - ' + Reflect.ownKeys(lineObject));
//console.log('Object.values - ' + Object.values(lineObject));
//console.log('lineObject = '+ lineObject.lineText);
//console.log('Object.entries(lineObject) - ' + Object.entries(lineObject));
//console.log('Object.entries(lineObjectClone) - ' + Object.entries(lineObjectClone));
//console.log('lineObjectClone.lineText = ' + lineObject.lineText);
//console.log('lineObjectClone[1].lineText = ' + lineObjectClone.lineText);
//console.log('lineArray[0] = ' + lineArray[0].lineText);
console.log('lineArray = ' + lineArray);
console.log('numberOfLines = ' + numberOfLines);
for(let i = 0; i < numberOfLines; ++i ){
console.log('lineArray[i].lineText = ' + lineArray[i].lineText)
}
};
//does the element have the class specified?
function hasClass(elem, className) {
return elem.classList.contains(className);
};
<section>
<button id="test">Test</button>
<div class="lineNumber">
<div class="accordion-title">
<h3>Line</h3>
</div>
<div class="input-section" style="display: block;">
<div class="input-row">
<div class="input-container">
<label>Line Text :</label>
<input type="text" name="lineText" value="" class="lineText">
</div>
</div>
<div class="input-row">
<div class="button-container">
<div class="warning"></div>
<button class="addLine">Add Another Line</button>
</div>
</div>
</div>
</div>
</section>
One way to do this is to use a closure.
The purpose of a closure is to capture variables from the containing function so those variables can be used later, after the containing function exits.
A simple example could look like this:
let data = {
nameGenerator: 0
};
function addInput() {
// generate a new name and property in data object
let propertyName = String.fromCharCode("a".charCodeAt() + data.nameGenerator++);
// initialize property value to its name
data[propertyName] = propertyName;
// add <div><input value="(property)"></div> to container
let containerElement = document.getElementById("container");
let lineElement = document.createElement("div");
let inputElement = document.createElement("input");
lineElement.appendChild(inputElement);
containerElement.appendChild(lineElement);
// initialize input value (note: this does not bind the two, just initializes)
inputElement.value = data[propertyName];
// create a closure that binds the property to the element
inputElement.addEventListener("keyup", function () {
// inside this function, propertyName and inputElement
// are "captured" in the closure
data[propertyName] = inputElement.value;
})
}
Note that the propertyName and inputElement variables are defined in the outer addInput function, but they are captured in the closure that is created when you assign the anonymous function as an event listener.
Here is a fiddle with a complete working example: https://jsfiddle.net/b3ta60cn/
Every time I click the "Add to Cart button" it will update the cartarray[]. What I want to do is to add a new object in the cart for every click so that I can have multiple objects for every different Cart item.
(function() {
const cartbtn = document.querySelectorAll(".add_to_cart_button");
cartbtn.forEach(function(btn) {
btn.addEventListener("click", function(event) {
if (event.target.parentElement.classList.contains("add_to_cart_button")) {
let fullpath = event.target.parentElement.previousElementSibling.children[0].children[0].src;
const item = {};
item.img = fullpath;
let name = event.target.parentElement.previousElementSibling.children[3].children[0].textContent;
item.name = name;
let price = event.target.parentElement.previousElementSibling.children[3].children[1].textContent;
let finalprice = price.slice(1).trim();
item.price = finalprice;
const cartarray = [];
var product = function(name, price, img) {
this.name = name
this.price = price
this.img = img
};
cartarray.push(new product(name, finalprice, fullpath));
console.log(cartarray);
}
});
});
})();
<div class="product-item men">
<div class="product discount product_filter">
<div class="product_image">
<img src="images/product_1.png" alt="">
</div>
<div class="favorite favorite_left"></div>
<div class="product_bubble product_bubble_right product_bubble_red d-flex flex-column align-items-center"><span>-$20</span></div>
<div class="product_info">
<h6 id="item-name" class="product_name">Fujifilm X100T 16 MP Digital Camera (Silver)</h6>
<div class="product_price">$520.00</div>
</div>
</div>
<div class="red_button add_to_cart_button">add to cart</div>
</div>
I leave an answer rather than a comment because I still don't have the reputation to leave a comment. Provide the HTML code, as my colleagues said and we'll be able to answer.
Something 'fishy' I notice that may stop your code to work are these two lines of code:
const cartbtn = document.querySelectorAll(".add_to_cart_button");
if (event.target.parentElement.classList.contains("add_to_cart_button"))
It may be the '.' in the first line, or missing in the second line which stops your code working. I may be wrong, it's just an assumption without seeing your full code
cartarray should be declared outside of the addEventListener in order for the items in the cart to be persistent.
I would also suggest to place the creation of the product outside as well, although technically this is not required.
See the following as an example where the for loop is simulating your button clicks:
const cartarray = [];
const product = function(name, price, img) {
return {
name: name,
price: price,
img: img
}
};
for (let x = 1; x < 6; x++) {
cartarray.push(new product('p' + x, x + '.00', 'path/to/img' + x + 'png'));
}
console.log(cartarray);