1) I am rendering messeages according to JSON. Firstly, I need to show only 3 information from that JSON (JSON has 6 attrs). When user click on the rendered message, it should show additional information like description and I need get id of that div... Problem is, I cannot access that id...
I have main div messages, and then message_items are added to this div according to json. When I am trying to get ID of that div, it writes undefined...
My code looks like:
2) How to store additional information about that div which I dont want to be visible?
$(".messages").on('click','.message__item', function(e) {
documentView.clearContent();
var targetElement = event.target || event.srcElement;
alert(targetElement);
var id = $(this).attr("id"); // DOES NOT WORK - UNDEFINED
alert(contentPanelId);
const data = {
title: $(this).find(".title").text(),
date: $(this).find(".date").text(),
desc: document.getElementById("descr").value,
createdBy: document.getElementById("createdBy").value,
id: targetElement.id // DOES NOT WORK, UNDEFINED
};
documentView.renderDocument(data);
});
export const fillDocuments = (data) => {
console.log("DATA. "+ data);
for(var i = 0; i < data.length; i++){
const markup = `
<div class="message__item id=${data[i].id}>
<img src="../img/copy.svg" class="item-type">
<div class="title">
${data[i].title}
</div>
<div class="date">
${formatTimeForMessages(data[i].uploadDatetime)}
</div>
<div class="read">
XY
</div>
// THIS DOES NOT WORK FOR ME AGAIN
<input type="hidden" id="descr" value="${data[i].description}"></input>
<input type="hidden" id="createdBy" value="Someone"/>
</div>`;
console.log("MRK "+ markup);
elements.messages.insertAdjacentHTML("beforeend", markup);
}
};
First, your didn't close the class quote on near "message__item" name. And how store data in a way that isn't visible? use data attribute, se here. Bellow a working example.
$(".messages").on('click','.message__item', function(e) {
///documentView.clearContent();
var targetElement = event.target || event.srcElement;
alert(targetElement.nodeName);
console.log(this);
var id = $(this).attr("id"); // DOES NOT WORK - UNDEFINED
alert(id);
alert(this.dataset.title);
const data = {
title: $(this).find(".title").text(),
date: $(this).find(".date").text(),
desc: document.getElementById("descr").value,
createdBy: document.getElementById("createdBy").value,
id: targetElement.id // DOES NOT WORK, UNDEFINED
};
//documentView.renderDocument(data);
});
var fillDocuments = (data) => {
for(var i = 0; i < data.length; i++){
const markup = `
<div class="message__item" data-title="${data[i].title}" id=${data[i].id}>
<img src="../img/copy.svg" class="item-type">
<div class="title">
${data[i].title}
</div>
<div class="date">
${(data[i].uploadDatetime)}
</div>
<div class="read">
XY
</div>
// THIS DOES NOT WORK FOR ME AGAIN
<input type="hidden" id="descr" value="${data[i].description}"></input>
<input type="hidden" id="createdBy" value="Someone"/>
</div>`;
$("#messages").get(0).insertAdjacentHTML("beforeend", markup);
}
};
fillDocuments([
{id:1, uploadDatetime:Date(), title: 'Title here', description: 'Desc...'}
])
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="messages" class="messages">
</div>
Related
I think I know what the issue is, I suspect its this causing the issue?
let budgetArray = JSON.parse(window.localStorage.getItem(STORAGE_KEY) ?? "[]");
This is basically getting the stored data from here
/*----Store Stored budget list----*/
function storedEntry(){
const saveData = makeNewBudget();
const myJSON = JSON.stringify(saveData);
window.localStorage.setItem(STORAGE_KEY, myJSON);
}
The makenewbudget() is a function that contains an object of user input data
function makeNewBudget(){
const data = {
id: createId(),
cashflowNew: el.cashflow.value,
catagoryNew: el.catagory.value,
labelNew: el.label.value,
dateNew: createdDate(),
numberNew: el.number.value,
};
return data;
}
I have a function that when you click the create budget button its meant to add to the list
/*----form validation----*/
let budgetButton = document.querySelector(".budget-button");
let label = document.querySelector(".label");
let num = document.querySelector(".number");
let entry = document.querySelector(".entry")
budgetButton.addEventListener("click", () => {
if (!label.value || !num.value) {
alert("please make sure all inputs are filled");
}
budgetArray.push(makeNewBudget())
renderList();
storedEntry();
});
This is the renderList() function
/*----Render Budget List----*/
function renderList(){
el.list.innerHTML = budgetArray.map(function (data,i) {
return `<div class="entry">
<div class="list">
<button onclick="deleteItem(event, ${i})" class="Archive" data-id="${data.id}">
<img src="../resources/Images/archive.png" alt="Archive">
</button>
<button onclick="editItem(event, ${i})" class = "edit" data-id="${data.id}" class = "edit" data-id="${data.id}">
<img src="../resources/Images/edit.png" alt="Edit">
</button>
<div class="input" data-id="${data.id}"></div>
<label class="dateNew">${data.dateNew}</label>
<label class="cashflowNew">${data.cashflowNew}</label>
<label class="catagoryNew">${data.catagoryNew}</label>
<label class="labelNew">${data.labelNew}</label>
<label class="numberNew">${data.numberNew}</label>
</div>
</div>
<label class="total"></label>`;
});
}
I am not sure what I can do to fix the Uncaught TypeError: budgetArray.push is not a function
The error does not appear if I change
let budgetArray = JSON.parse(window.localStorage.getItem(STORAGE_KEY) ?? "[]");
to
let budgetArray = [];
So I am a bit stumped in how to fix that, because The localStorage.getItem needs to check the array for the stored data.
I am trying to add an event listener to my "degree section div" but it is not working nor am I getting any errors. I have tried multiple ways of traversing the DOM to reach the "degree-section" div but to no avail.
Any kind of help is welcome and appreciated
Code:
let city = document.querySelector('#city');
let searchbtn = document.querySelector('.search-btn');
let city_name = document.querySelector('.city-name');
let temp = document.querySelector('.temp');
let feels_like = document.querySelector('.feels-like');
let humidity = document.querySelector('.humidity');
let locationIcon = document.querySelector('.weather-icon');
let checkbox = document.getElementById('celcius');
let weather_sec = document.querySelector('.weather-info');
let degree_section = weather_sec.firstElementChild;
let degree_section_span = degree_section.getElementsByTagName('span')[0];
//let wind = document.querySelector('.wind');
async function getUrl(city) {
try {
let theUrl = url + city + '&appid=' + apiKey;
let response = await fetch(theUrl, {
mode: 'cors'
})
let data = await response.json();
//Get data from api and change html content based on the recieved data
let temp_data = data.main.temp
temp.textContent = temp_data;
let feels_like_data = data.main.feels_like;
feels_like.textContent = feels_like_data + "K";
let humidity_data = data.main.humidity;
humidity.textContent = humidity_data;
let {
icon
} = data.weather[0];
locationIcon.innerHTML = `<img src="icons/${icon}.png">`;
//change K to C
degree_section.addEventListener('click', () => {
//logging a message just to check if it is working
console.log("c")
})
} catch (err) {
let error = document.createElement('span')
error.className = "error";
error.textContent = "Location does not exist"
let top_center_div = document.querySelector('.top-center')
top_center_div.appendChild(error)
city_name.textContent = "No city found"
}
}
searchbtn.addEventListener('click', (e) => {
let cityName = city.value;
city_name.textContent = cityName
console.log(cityName)
getUrl(cityName)
})
<body>
<div class="loc-container">
<div class="location">
<h1 class="city-name">City</h1>
<div class="weather-icon"><img src="icons/unknown.png" /></div>
</div>
</div>
<div class="weather-info">
<div class="degree-section">
<h2 class="temp">0.0</h2>
<span>K</span>
</div>
<div class="info-section">
<div class="info-flex">
<h3 class="feels-like">0K</h3>
<h4>Feels Like</h4>
</div>
<div class="info-flex">
<h3 class="humidity">0</h3>
<h4>Humidity</h4>
</div>
<div class="info-flex">
<h3 class="wind">0</h3>
<h4>Wind</h4>
</div>
</div>
</div>
<div class="top-center">
<div class="form">
<input type="text" name="city" id="city" required>
<label for="city" class="label-name"><span class="search-name">Search City...</span></label>
</div>
<!-- <i class="fas fa-search search-btn"></i> -->
<i class="material-icons search-btn" style="font-size: 35px;">search</i>
</div>
<script src="weather.js"></script>
</body>
This is what "data" looks like
{"coord":{"lon":72.8479,"lat":19.0144},"weather":[{"id":711,"main":"Smoke","description":"smoke","icon":"50d"}],"base":"stations","main":{"temp":303.14,"feels_like":303.45,"temp_min":301.09,"temp_max":303.14,"pressure":1014,"humidity":45},"visibility":2500,"wind":{"speed":3.09,"deg":120},"clouds":{"all":20},"dt":1638773692,"sys":{"type":1,"id":9052,"country":"IN","sunrise":1638754125,"sunset":1638793848},"timezone":19800,"id":1275339,"name":"Mumbai","cod":200}
Thank you in advance!
I believe the problem is with
let degree_section_span = degree_section.getElementsByTagName('span')[0];
since it selects the wrong element. Try changing it to
let degree_section_span = weather_sec.querySelector('.check');
and see if it works. You can also change the variable name to something more appropriate, while you're at it.
EDIT:
I think this is what you're trying to do. For the sake of siplicity , I removed everything not related to temp:
let target = weather_sec.querySelector("div.check"),
temp_data = data.main.temp;
temp.textContent = temp_data;
target.addEventListener('click', () => {
cel = parseInt(temp_data) - 273.15;
temp.textContent = cel.toFixed(2);
temp.nextElementSibling.textContent = "C";
});
So after 48hrs of debugging I finally figured out what is wrong. If you see in my HTML I have a div.top-center at the bottom. And due to some dimension issues in my css file the height of div.top-center spanned the entire page so essentially all of my divs were being wrapped inside div.top-center so even if I assigned a click event to my div.degree-section the target was always div.top-center and that is why the click event was not showing the proper output.
I have no expertise in javascript but I want to render this data which is showing in my console.log below
How can I make forloop or something like that to render this data in my html input?
create.html
<div class="col-sm-2">
<div class="form-group">
<label>Expected Values</label>
<input type="text" class="form-control" value="{{vital.expected_values}}" readonly>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<label>Price</label>
<input type="text" class="form-control" value="{{vital.price}}" readonly>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$("#id_vitals").change(function () {
var vitals = $(this).val();
$.ajax({
url: $('#personForm').data('url'),
data: { 'vital_id': vitals },
success: function (response) {
console.log(response[vitals['name']])
}
});
});
})
</script>
I would do it somehow like that:
// Your data
let dataArray = [{data: 1, otherData: 2, elseData: 3}]
// The element, where you want to show it
let targetElement = document.getElementById('your-targer-id');
// The container element for elements
let newContainer = document.createElement('ul');
// Pure JS loop, easy to understand what is happening
// But you can also do it with .map();
for (let i = 0; i < dataArray.length; i++) {
// Add every line
newContainer.innerHTML+='<li>' + dataArray[i].data + '</li>';
// Or other things, depending how you want to show the data
newContainer.innerHTML+='<li> data value is: ' + dataArray[i].data + ' and otherData value is: ' + dataArray[i].otherData + '</li>'; //etc
}
// Append created list in target element
targetElement.appendChild(newContainer);
EDIT - now I see, that you want to display multiple values in text input, rather like so:
let dataArray = [...your-data-array]
let targetElement = document.getElementById('target-input');
for (let i = 0; i < dataArray.lenght; i++) {
// loop throug elements and add it to value attribute of input, separated by coma.
targetElement.value+=dataArray[i].expected_values + ', ';
}
I'm trying to use javascript to create a set of elements over and over again once the user enters a text where it would display the text with a button with an image in it to the side of it but I could not find a way to do it efficiently.
The current method I was going to create would require each element to have a id tag to it so that I could call appendChild to join the elements together.
I also need to have a create element be appended into another create element which adds to the issues
This is what I'm trying to achieve in the html code (the div would not be needed to be created as it is in the html code already)
function addToList(input) {
console.log(x);
let task = document.createElement('p');
task.id = x;
task.appendChild(document.createTextNode(input));
document.getElementById('listOfTasks').appendChild(task);
addCheckBox(x);
x++;
}
function addCheckBox(id) {
let checkBox = document.createElement('a');
checkBox.className = 'button is-rounded is-small';
checkBox.id = 'checkBox';
document.getElementById(id).appendChild(checkBox);
let a = document.createElement('span');
a.className = 'icon is-small';
a.id = 'apple';
document.getElementById(id).appendChild(a);
let b = document.createElement('i');
b.className = 'fas fa-check';
document.getElementById(id).appendChild(b);
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css"/>
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
<div class="container">
<div id="listOfTasks"></div>
</div>
<section class="section">
<div class="container">
<div class="field box form-popup" id="addTask">
<div class="control">
<div class="field is-grouped">
<label class="label"><b>Task to add</b></label>
</div>
<input
type="text"
class="input"
placeholder="Enter Task"
id="task"
required
/>
</div>
<button
type="button submit"
class="button is-success"
id="submit"
onclick="closeForm()"
>
Add
</button>
</div>
</div>
</section>
The current output is shown as
Would be grateful if anyone knows a better method to do this
Make a function that reduces boilerplate code when creating element
function create(name, props, children) {
let elem = document.createElement(name); // create it
const parent = props.parent // we use parent prop elsewhere
let keys = Object.keys(props) // collect keys
keys = keys.filter(function(key) { // remove parent prop from keys
return key !== 'parent'
})
keys.forEach(function(key) { // assign props to element
elem.setAttribute(key, props[key])
})
if (children && children.length) { // add children to element
children.forEach(function(child) {
elem.appendChild(child)
})
}
if (parent) { // attach to parent
document.getElementById(id).appendChild(elem);
}
return elem // return it, to customize further
}
And then
function addCheckBox(id) {
create('a', {
id: 'checkBox', // simple prop
parent: id, // parent prop
class: 'button is-rounded is-small' // simple prop
})
var span = create('span', {
parent: id,
id: 'apple',
class: 'icon is-small'
}, [create('i', { // demo of children
class: 'fa fa-check'
}])
span.setAttribute('data-something', 1) // demo of customizing
}
I am working on a wikipedia viewer (https://codepen.io/rwiens/pen/YLMwBa) which is almost done but I have 2 problems:
I cannot submit my search results when I press enter. I have added an event listener and can console.log "hello: but I cannot call the searchWiki function.
When I do a new search the results are appended to the bottom pf my old results.
I've searched the web for the last half day and am stuck. Any help would be appreciated.
<div class="container">
<div class="banner text-center align-items">
<h1>Wiki Search</h1>
<p>Search for articles on Wikipedia</p>
</div>
<form action="" class="text-center">
<input type="search" id="search-box" placeholder="Search Here">
<div class="buttons">
<input type="button" onclick="searchWiki()" id="search-
button" value="Search">
<input type="submit" value="Feel Lucky?">
</div>
</form>
<div class="articles">
<ul id="results">
</ul>
</div>
</div>
<script type="test/javascript">
const searchBox = document.getElementById('search-box');
const sButton = document.getElementById('search-button');
const results = document.getElementById('results');
window.onload = function() {
searchBox.focus();
};
const searchWiki = () => {
const keyword = searchBox.value;
fetch("https://en.wikipedia.org/w/api.php?
&origin=*&action=opensearch&search=" + keyword + "&limit=5", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ query: event.currentTarget.value })
})
.then(response => response.json())
.then((data) => {
console.log(data);
build(data);
});
}
const build = (data) => {
let title = data[1];
let description = data[2];
let url = data[3];
for(let x = 0; x < 5; x++){
console.log(title);
const item = `<a href="${url[x]}" target="#">
<li>
<h5>${title[x]}</h5>
<p>${description[x]}.</p>
</li>
</a>`;
results.insertAdjacentHTML("beforeend", item);
}
}
searchBox.addEventListener("keyup", function(event) {
if (event.key === "Enter") {
searchWiki;
}
});
</script>
You are not calling searchWiki as function. Call it like this searchWiki();
Also you need to remove the form tag. Because you have button type elements in it , it is by default submitting your form on enter press.
Also clear results div before appending new data like this
results.innerHTML = ""
for(let x = 0; x < 5; x++){
console.log(title);
const item = `<a href="${url[x]}" target="#">
<li>
<h5>${title[x]}</h5>
<p>${description[x]}.</p>
</li>
</a>`;
results.insertAdjacentHTML("beforeend", item);
}
Check updated codepen
when I put searchWiki I am still not calling the search unfortunately. also, when i add results.innerHTML = "" my search only comes back with one result.
You need to add an event listener for the form submit. In that you need to cancel the event ( event.preventDefault() ).
Empty your results as #NanditaAroraSharma pointed out (best before calling build function)
Solved it. Removed the form as it was trying to send me to another page.
<div class="text-center">
<input type="search" id="search-box" placeholder="Search Here">
<div class="buttons">
<input type="button" onclick="searchWiki()" id="search-
button" value="Search">
<input type="button"
onclick="location.href='https://en.wikipedia.org/wiki/Special:Random';"
value="Feel Lucky?">
</div>
for building the html i took part of it out of the for loop.
const build = (data) => {
let title = data[1];
let description = data[2];
let url = data[3];
results.innerHTML = "";
for(let x = 0; x < 5; x++){
console.log(title);
const item = `<a href="${url[x]}" target="#">
<li>
<h5>${title[x]}</h5>
<p>${description[x]}.</p>
</li>
</a>`;
results.innerHTML += item;
}
}