I want to display comments line by line in a div but the div is closing first and after that the comments are listing.
if (comments.num_replies > 0) {
$("#showComment").append(`<div id="replyContainer${comments.comment_id}" class="replyContainer">`);
comments.comment_replies.forEach((replies) => {
$("#showComment").append(`
<div class="img-comment reply">
<img src="${home_url}img/user.png">
<div class="m-2 p-3 ">
<div class="user-date"><p class="username">#${replies.replier_username}</p><p class="date">${replies.dates}</p></div>
<p class="comment_content">${replies.reply_comment_content.replace(/\n/g, "<br>")}</p>
</div>
</div>
`)
});
$("#showComment").append(`</div>`);
}
You can try something like this
if (comments.num_replies > 0) {
let replies = comments.comment_replies.map((replies) => (
`<div class="img-comment reply">
<img src="${home_url}img/user.png">
<div class="m-2 p-3 ">
<div class="user-date"><p class="username">#${replies.replier_username}</p><p class="date">${replies.dates}</p></div>
<p class="comment_content">${replies.reply_comment_content.replace(/\n/g, "<br>")}</p>
</div>
</div>`
));
$("#showComment").append(`<div id="replyContainer${comments.comment_id}" class="replyContainer">${replies.join('')}</div>`);
}
Related
I'm looking for solutions to display the right movie information in my overlay.
I have a "popup window" that appears when i click on a movie and it is supposed to display movie's informations in it but when I click on a movie, no matter which one it is, it only displays the last movie informations, what Should I do to fix it ?
const movieIntegration =() => {
allMovies.map(movie=> {
movieGallery.innerHTML += `<div class="imgContainer">
<img src="${movie.img}" alt="${movie.name}">
<div class="titleContainer">
<div class="movieTitle"> ${movie.name} </div>
<div class="seemore"> See more </div>
</div>
</div>`
const seemore = document.querySelectorAll(".seemore")
seemore.forEach(elm => {
elm.addEventListener("click",() => {
pageContainer.innerHTML += `<div class="popupContainer">
<div class="popup">
${movie.name}
<div id="likeButton">
<img src="img/like.png">
</div>
<div id="editButton">
<img src="img/edit.png">
</div>
<a href="submit.html">
<div id="addingButton">
<img src="img/add.png">
</div>
</a>
</div>
</div>`
console.log(true)
}, true)
})
})
}
the problem is that you are getting all the .seemore element for each movie and you are editing the content of ALL elements for each movie, so the last movie will overwrite the content for all the previous.
A solution could be something like this:
const movieIntegration = () => {
allMovies.map((movie) => {
movieGallery.innerHTML += `<div class="imgContainer">
<img src="${movie.img}" alt="${movie.name}">
<div class="titleContainer">
<div class="movieTitle"> ${movie.name} </div>
<div class="seemore"> See more </div>
</div>
</div>`
})
const seemore = document.querySelectorAll('.seemore')
seemore.forEach((elm, i) => {
elm.addEventListener(
'click',
() => {
pageContainer.innerHTML += `<div class="popupContainer">
<div class="popup">
${allMovies[i].name}
<div id="likeButton">
<img src="img/like.png">
</div>
<div id="editButton">
<img src="img/edit.png">
</div>
<a href="submit.html">
<div id="addingButton">
<img src="img/add.png">
</div>
</a>
</div>
</div>`
},
true
)
})
}
In this way you are mapping the .seemore elements AFTER you finish the map of allMovies and, for each .seemore element you get the associated movie and write his name inside.
I have 32 items in my array, all of them have these properties: id, word, image. User has to guess what's in all the images and write their guess in inputs (so 32 inputs in total). I need to check if the input equals my arrays property "word" and then when clicked a button (type submit, all my pic's and inputs are in a form) display some text for example "Oops! Guess again" if wrong and "Yay! You got it correctly" if right. The text should appear below every input. I displayed all the pictures and inputs with a forEach, and i'm using bulma framework for this page:
const wordBox = info.forEach((words) => {
mainColumns.innerHTML += `
<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${words.image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" id="text" type="text" placeholder="Įvesk žodį">
</div>
</div>
<div class="content">
Content
</div>
</div>
</div>
</div>`;
});
Any ideas?
This is how it should look like (the result should appear in content place)
Something like this
I use change instead of a button click
const info = [
{word:"flower",image:"flower.gif"},
{word:"boat",image:"boat.gif"}
];
const mainColumns = document.getElementById("mainColumns");
mainColumns.innerHTML = info.map(({image,word}) =>
`<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" data-word="${word}" type="text" placeholder="Įvesk žodį">
<span class="correct hide">Yay</span>
<span class="wrong hide">NOO</span>
</div>
</div>
<div class="content">
Content
</div>
</div>
</div>
</div>`).join("");
mainColumns.addEventListener("change",function(e) {
const correct = [...mainColumns.querySelectorAll("[data-word]")].map(input => {
if (input.value) {
const correct = input.value === input.dataset.word;
parent = input.closest("div");
parent.querySelector(".correct").classList.toggle("hide",!correct)
parent.querySelector(".wrong").classList.toggle("hide",correct);
return correct ? 1 : 0;
}
else return 0;
}).reduce((a,b)=>a+b);
document.getElementById("correct").innerText = correct;
})
#mainColumns { display:flex; }
.hide { display: none; }
<div id="mainColumns"></div>
Correct: <span id="correct"></span>
What you can do is to filter the word array with word from the input value. Then check if the length is equal zero, No match, if the length is greater than one, then there is a match.
const status = wordBox.filter(item => item.word === inputWord)
I'd move towards keeping the objects and the HTML separate, binding the HTML to the object and vice versa. This means including a couple more properties to your array elements.
let info = [{
image: 'flower.png',
word: 'flower',
content: '',
guess: ''
}];
function bindWords() {
info.forEach((words) => {
mainColumns.innerHTML = `
<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${words.image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" data-word="${words.word}" type="text" placeholder="Įvesk žodį" value="${words.guess}">
</div>
</div>
<div class="content">
${words.content}
</div>
</div>
</div>
</div>`;
});
}
bindWords();
check.addEventListener('click', () => {
info = Array.from(document.querySelectorAll('.card')).map(el => ({
image: el.querySelector('img').src,
word: el.querySelector('.input').dataset.word,
guess: el.querySelector('.input').value,
content: el.querySelector('.input').value === el.querySelector('.input').dataset.word ?
'Correct' : 'Incorrect'
}));
bindWords();
});
<div id="mainColumns"></div>
<button id="check">Check Answers</button>
I have some HTML - pretty nasty, but not mine and so I don't have control over it. I need to extract some data from the form, the First name value (ABDIGANI) and the Surname value (AHMED). What is the best way to do this with javascript?
<div class="voffset3"></div>
<div class="container well panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-md-3">
<span class="ax_paragraph">
First name
</span>
<div class="form-group">
<div class="ax_h5">
ABDIGANI
</div>
</div>
</div>
<div class="col-md-3">
<span class="ax_paragraph">
Surname
</span>
<div class="form-group">
<div class="ax_h5">
AHMED
</div>
</div>
</div>
</div>
</div>
</div>
</div>
You could consider HTML in most cases well structured. Try this the following snippet.
Edit: did a change due to the first comment.
Edit: if you have more than one rows, you should use
document.querySelectorAll('.container > .panel-body > .row');
and fetch the pairs for each found element as below.
const markers = ['First name', 'Surname'];
const mRx = [new RegExp(markers[0]), new RegExp(markers[1])];
function findMarker(element) {
for(let i = 0; i < mRx.length; i++) {
if(element.innerHTML.match(mRx[i])) {
return markers[i];
}
}
return null;
}
function findValue(el) {
return el.parentElement.querySelector('.form-group > div').innerHTML.trim();
}
const pairs = [... document.querySelectorAll('.ax_paragraph')]
.map(el => {
return {el: el, mk: findMarker(el)};
})
.filter(n => n.mk !== null)
.map(o => {
return {key: o.mk, value: findValue(o.el)};
});
console.log(pairs);
var x = document.querySelectorAll(".panel-body > div >.col-md-3 > div > div");
x.forEach(myFunction);
function myFunction(item, index) {
//console.log(item.innerHTML.trim());
if (index===0){
console.log("First name : "+item.innerHTML.trim());
}
if (index===1){
console.log("Surname : "+item.innerHTML.trim());
}
}
<div class="voffset3"></div>
<div class="container well panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-md-3">
<span class="ax_paragraph">
First name
</span>
<div class="form-group">
<div class="ax_h5">
ABDIGANI
</div>
</div>
</div>
<div class="col-md-3">
<span class="ax_paragraph">
Surname
</span>
<div class="form-group">
<div class="ax_h5">
AHMED
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Check this
const firstName = document.querySelector('.row .form-group div').textContent.trim();
const surname = document.querySelector('.row > div:last-child .form-group div').textContent.trim();
note: Its better to change html according to functionality needs, like if you need firstname then you must keep an id attribute to div which is having first name, same goes to surname. then select those fields using id selector, because even if you change html page structure in future, functionality will not get effected.
Check below for reference on how the html should actually be(just to make sure you know it, but the solution you are seeking is above in first two lines)
eg:
<div class="voffset3"></div>
<div class="container well panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-md-3">
<span class="ax_paragraph">
First name
</span>
<div class="form-group">
<div class="ax_h5" id="firstNameField">
ABDIGANI
</div>
</div>
</div>
<div class="col-md-3">
<span class="ax_paragraph">
Surname
</span>
<div class="form-group">
<div class="ax_h5" id="surnameField">
AHMED
</div>
</div>
</div>
</div>
</div>
</div>
</div>
document.querySelector('.form-group > div').textContent but without modifying the html there is no way to distinguish first name and surname.
If you can't edit the HTML, you can use the XPATH for Example.
I'm trying to create a show/hide div for when my mouse enters and leaves the container. I was following this example here (https://upmostly.com/tutorials/react-onhover-event-handling-with-examples) but I've run into a problem when I hover my mouse over the 'delete-container' div, it disappears. This problem occurs because it takes the action onMouseLeave. Is there a way I can fix this or possibly make my solution better? Here is a demo of what is happening (https://i.gyazo.com/528d909625b6b3828325c4e62894d1c3.mp4).
import React, { useState } from 'react';
import axios from 'axios';
export default function JobInfo({ jobs_info }) {
const [isShown, setIsShown] = useState(false);
const changeBackground = (x) => {
x.target.style.backgroundImage =
'linear-gradient(to right, #4639a7, #78019c)';
};
const changeBackground2 = (x) => {
x.target.style.background = 'rgb(37, 45, 73)';
};
return (
<div className='row'>
<div
className='container'
onMouseEnter={() => setIsShown(true)}
onMouseLeave={() => setIsShown(false)}
>
<div className='row'>
<div className='job-title'>{jobs_info.title}</div>
</div>
<div className='row wrapper'>
<div className='category-title'>Category</div>
<div className='location-title'>Location</div>
<div className='type-title'>Type of Job</div>
<div className='creator-title'>Job Creator</div>
</div>
<div className='row wrapper'>
<div className='category'>{jobs_info.job_team.title}</div>
<div className='location'>
{jobs_info.job_location.title}
</div>
<div className='type'>{jobs_info.job_work_type.title}</div>
<div className='creator'>{jobs_info.user.name}</div>
</div>
</div>
<div
className='counter-container'
id='counter-container'
onMouseEnter={changeBackground}
onMouseLeave={changeBackground2}
>
Candidates <br />
{jobs_info.candidates_count}
</div>
{isShown && (
<div className='delete-container center'>
<ion-icon id='trash' name='trash'></ion-icon>
</div>
)}
</div>
);
}
The issue happens because delete-container is outside of the container hierarchy and hence mouseleave event is triggered on the container. Render the delete-container as a child of container and style it accordingly
return (
<div className='row'>
<div
className='container'
onMouseEnter={() => setIsShown(true)}
onMouseLeave={() => setIsShown(false)}
>
<div className='row'>
<div className='job-title'>{jobs_info.title}</div>
</div>
<div className='row wrapper'>
<div className='category-title'>Category</div>
<div className='location-title'>Location</div>
<div className='type-title'>Type of Job</div>
<div className='creator-title'>Job Creator</div>
</div>
<div className='row wrapper'>
<div className='category'>{jobs_info.job_team.title}</div>
<div className='location'>
{jobs_info.job_location.title}
</div>
<div className='type'>{jobs_info.job_work_type.title}</div>
<div className='creator'>{jobs_info.user.name}</div>
</div>
{isShown && (
<div className='delete-container center'>
<ion-icon id='trash' name='trash'></ion-icon>
</div>
)}
</div>
<div
className='counter-container'
id='counter-container'
onMouseEnter={changeBackground}
onMouseLeave={changeBackground2}
>
Candidates <br />
{jobs_info.candidates_count}
</div>
</div>
);
However you could simply use CSS hover event to show or hide the delete-container without the need for state after renderingdelete-containeras a child ofcontainer`
.scss
.container {
.delete-container {
display: none;
// other styles
}
&:hover {
.delete-container {
display: block;
}
}
// other styles
}
This is my React.component code. OnClick event executed on page initialization and i cant fix this, i tried 2 pull onClick over the maping, but this has no sense:
handleClick (id){
alert(id);
}
render() {
var tmp = this.handleClick;
return(
<div className="thirteen wide column">
<div className="rrc-title">Магазины, нарушающие РРЦ</div>
<div className="custom-hr"></div>
<div className="ui grid">
{
jsonResult.data.map(function(el){
return (
<div className="three wide column">
<div className="store-item-bad" onClick={tmp(el.siteId)}>
<div className="siteName">{el.siteName}</div>
{
el.values.map(function(element){
var processWidth ={
background : element.color,
width: element.percent+'%'
}
return(
<div className="BarItem">
<div className="progressBar">
<div className="ui tiny progress">
<div className="bar" style={processWidth}></div>
</div>
</div>
<div className="progressCounter">{element.count}</div>
</div>)
})
}
</div>
</div>
);
})
}
</div>
<div className="rrc-title">Магазины, соблюдающие РРЦ</div>
<div className="custom-hr"></div>
<div className="ui grid">
{
jsonResult.data.map(function(el){
return (
<div className="three wide column">
<div className="store-item-ok">
<div className="siteName">{el.siteName}</div>
{
el.values.map(function(element){
var processWidth ={
background : element.color,
width: element.percent+'%'
}
return(
<div className="BarItem">
<div className="progressBar BarFloatingLeft">
<div className="ui tiny progress">
<div className="bar" style={processWidth}></div>
</div>
</div>
<div className="progressCounter">{element.count}</div>
</div>)
})
}
</div>
</div>
);
})
}
</div></div>
);
}
It's easy thing, but i can't focus right now, so i need ur help guys:)
Try:
onClick={this.handleClick.bind(this,el.siteId)} or
onClick={tmp.bind(this,el.siteId)}
And add arrow func in map:
map(e=>{})