how to create generic html with javascript - javascript

I have the following html:
<div id="prog" class="downloads clearfix">
<div class="item">
<div class="image_container">
<img src="/img/downloads/company.png" width="168" height="238" alt="">
</div>
<div class="title">
pricelist: <label id="pr1"></label>
</div>
<div class="type">
pdf document
</div>
<div class="link">
<a id="pdfdocument" class="button" target="_blank" href="#">start Download </a>
</div>
</div>
</div>
I want build HTML which is inside the <div id="prog"> with Javascript:
<div id="prog" class="downloads clearfix"></div>
I'm trying to use this Javascript, but without success:
var tmpDocument, tmpAnchorTagPdf, tmpAnchorTagXls, parentContainer, i;
parentContainer = document.getElementById('prog');
for (i = 0; i < documents.length; i++) {
tmpDocument = documents[i];
tmpAnchorTagPdf = document.createElement('a id="pdfdocument" ');
tmpAnchorTagPdf.href = '/role?element=' + contentElement.id + '&handle=' + ope.handle;
tmpAnchorTagPdf.innerHTML = 'start Download';
tmpAnchorTagXls = document.createElement('a');
tmpAnchorTagXls.href = '/role?element=' + contentElement.id + '&handle=' + ope.handle;
tmpAnchorTagXls.innerHTML = 'start Download';
parentContainer.appendChild(tmpAnchorTagPdf);
parentContainer.appendChild(tmpAnchorTagXls);
}

If this is a section of code that you will be using more than once, you could take the following approach.
Here is the original div without the code you want to create:
<div id="prog" class="downloads clearfix">
</div>
Create a template in a hidden div like:
<div id="itemtemplate" style="display: none;">
<div class="item">
<div class="image_container">
<img src="/img/downloads/company.png" width="168" height="238" alt="">
</div>
<div class="title">
pricelist: <label></label>
</div>
<div class="type">
pdf document
</div>
<div class="link">
<a class="button" target="_blank" href="#">start Download </a>
</div>
</div>
</div>
Then duplicate it with jquery (OP originally had a jquery tag; see below for JS), update some HTML in the duplicated div, then add it to the document
function addItem() {
var item = $("#itemtemplate div.item").clone();
//then you can search inside the item
//let's set the id of the "a" back to what it was in your example
item.find("div.link a").attr("id", "pdfdocument");
//...the id of the label
item.find("div.title label").attr("id", "pr1");
//then add the objects to the #prog div
$("#prog").append(item);
}
update
Here is the same addItem() function for this example using pure Javascript:
function JSaddItem() {
//get the template
var template = document.getElementById("itemtemplate");
//get the starting item
var tempitem = template.firstChild;
while(tempitem != null && tempitem.nodeName != "DIV") {
tempitem = tempitem.nextSibling;
}
if (tempitem == null) return;
//clone the item
var item = tempitem.cloneNode(true);
//update the id of the link
var a = item.querySelector(".link > a");
a.id = "pdfdocument";
//update the id of the label
var l = item.querySelector(".title > label");
l.id = "pr1";
//get the prog div
var prog = document.getElementById("prog");
//append the new div
prog.appendChild(item);
}
I put together a JSFiddle with both approaches here.

Related

Fire JS code for every element with the same class

I have a cart page with multiple products that have a new price. I now want to show the customer, using JS, how much he can save. For that I use my very basic knowledge of JS to write the old and new price into a variable, replace stuff I don't want in there like "€" and do my math. Then I create a new div with a certain text and how much the customer can save. What I want to achieve is that he writes that under every product.
As you can see from the snippet he only does that for the first product. I need some kind of loop or anything where he does that code for every product in the cart. So far I searched for 2 hours and couldn't find a hint. Maybe you guys and girls can help me.
var neuerpreis = document.querySelector(".price.price--reduced").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
var alterpreis = document.querySelector(".price.price--reduced .price__old").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
var difference = (alterpreis - neuerpreis).toFixed(2);
var newDiv = document.createElement("div");
var newContent = document.createTextNode(("You save ") + difference + (" €"));
newDiv.appendChild(newContent);
document.querySelector(".cart-item__price").appendChild(newDiv);
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 66,95<span class="price__old">
<span class="price__currency">€</span> 79,00</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 100,95<span class="price__old">
<span class="price__currency">€</span> 79,00</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
You can use querySelecetorAll and relative addressing
I select the .cart-item__price as the relevant container
Then I set some content as default
Note I do not convert to the string (toFixed) until I want to present it.
The INTL number formatter could also be used here
[...document.querySelectorAll(".cart-item__price")].forEach(div => {
const neuerpreis = div.querySelector(".price--reduced").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
const alterpreis = div.querySelector(".price__old").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
const difference = alterpreis - neuerpreis;
let newContent = document.createTextNode("No savings on this product")
const newDiv = document.createElement("div");
if (difference > 0) {
newContent = document.createTextNode(("You save ") + difference.toFixed(2) + (" €"));
}
newDiv.appendChild(newContent);
div.appendChild(newDiv);
})
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 66,95
<span class="price__old">
<span class="price__currency">€</span> 79,00
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 100,95<span class="price__old">
<span class="price__currency">€</span> 79,00</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
var el = document.querySelectorAll(".test_class");
for (i = 0; i < el.length; i++) {
el[i].innerHTML = "test"+i
}
<div class="test_class">hey</div>
<div class="test_class">hey</div>
<div class="test_class">hey</div>
<div class="test_class">hey</div>
Here you go

How to create a data object from the list of displayed element in the html

My html is like below:
<div class="list-item">
<div class="details">
<a href="https://link_to_Item_1" />
</div>
</div>
<div class="list-item">
<div class="details">
<a href="https://link_to_Item_2" />
</div>
</div>
<div class="list-item">
<div class="details">
<a href="https://link_to_Item_3" />
</div>
</div>
Using jquery, I want to create an object like following from the above HTML:
[
{
position :1,
url: "https://link_to_Item_1"
},
{
position :"2",
url: "https://link_to_Item_1"
},
{
position :"3",
url: "https://link_to_Item_2"
}
]
I tried something like below:
var myData = [];
var myDataElements = {};
$('.list-item').find('a').each(function(index, ele){
myDataElements.position = index;
myDataElements.url = $(this).attr('href');
myData.push(myDataElements);
});
But the result was the position and URL became the same for all elements in myData.
The issue is you are declaring the object outside. But you need the object in each iteration, declare that inside the function:
var myData = [];
$('.list-item').find('a').each(function(index, ele){
var myDataElements = {};
myDataElements.position = index + 1;
myDataElements.url = $(this).attr('href');
myData.push(myDataElements);
});
console.log(myData);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="list-item">
<div class="details">
<a href="https://link_to_Item_1" />
</div>
</div>
<div class="list-item">
<div class="details">
<a href="https://link_to_Item_2" />
</div>
</div>
<div class="list-item">
<div class="details">
<a href="https://link_to_Item_3" />
</div>
</div>
You can also use jQuery's .map() and .get() like the following way:
var myData = $('.details').map(function(i, el){
return {
position: i+1,
url: $(el).find('a').attr('href')
}
}).get();
console.log(myData);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="list-item">
<div class="details">
<a href="https://link_to_Item_1" />
</div>
</div>
<div class="list-item">
<div class="details">
<a href="https://link_to_Item_2" />
</div>
</div>
<div class="list-item">
<div class="details">
<a href="https://link_to_Item_3" />
</div>
</div>
You need to initialize the variable myDataElements inside the loop :
var myDataElements = {};
And make sure you're closing the anchor tag well like :
Instead of :
<a href="https://link_to_Item_1" />
NOTE: You can increase the index by 1 if you want to start counting from 1 instead of zero since the index is zero-based.
var myData = [];
$('.list-item a').each(function(index, ele) {
var myDataElements = {};
myDataElements.position = index + 1;
myDataElements.url = $(this).attr('href');
myData.push(myDataElements);
});
console.log(myData);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="list-item">
<div class="details">
</div>
</div>
<div class="list-item">
<div class="details">
</div>
</div>
<div class="list-item">
<div class="details">
</div>
</div>
myDataElements here pointing to the same object. And with each iteration you are basically changing the value of its 2 properties, position and url and then pushing it to the array. All array elements of myData are same object which you created here var myDataElements = {};. That's is why you ended up with same objects in myData.
What you want here is:
myData.push(Object.assign({}, myDataElements);
// or myData.push({...myDataElements});
Now you are creating a new object by copying the myDataElements before pushing it it the array myData. This gives you the desired output.

How to find elements with attr id after click?

Basically, I'm working with three tabs called 'Monday', 'Tuesday' and 'Favorites'. I have a toggle icon which is an empty heart at start => ('.favorite i') within each box. If I'm in Monday and click on the icon the empty heart turns to be filled out and the parent is cloned and added to the '#fav' tab.
When clicking in the heart within the cloned div the whole box gets removed from '#fav' tab but the icon within the original div doesn't get empty and keeps filled out.
So I thought the only way to do this was to grab the id from the original and cloned div which is the same and change the toggle class from there.
Any help is appreciated!
I've created this fiddle to give a better overview of the issue:
https://fiddle.jshell.net/itsfranhere/nbLLc3L0/44/
HTML:
<div class="container">
<div class="tabs_main">
<div class="col-md-5"><a data-target="#mon" class="btn active" data-toggle="tab">Monday</a></div>
<div class="col-md-5"><a data-target="#tue" class="btn active" data-toggle="tab">Tuesday</a></div>
<div class="col-md-2"><a data-target="#fav" class="btn active" data-toggle="tab"><i class="fa fa-heart" aria-hidden="true"></i></a></div>
</div>
<div class="tab-content">
<div class="tab-pane active" id="mon">
<br>
<div class="spaces">
<div class="box-container">
<div class="box not-selected" id="box1">
<i class="fa fa-heart-o" aria-hidden="true"></i>
</div>
<div class="box-container">
<div class="box not-selected" id="box1">
<i class="fa fa-heart-o" aria-hidden="true"></i>
</div>
</div>
</div>
<div class="tab-pane" id="tue">
<br>
<div class="spaces">
</div>
</div>
<div class="tab-pane" id="fav">
<br>
</div>
</div>
</div>
JS:
// Clones
$('div.tab-pane').on('click', '.favorite', function(e) {
e.preventDefault();
var par = $(this).parents('.box');
var id = $(this).parents('.parent');
var idFind = id.attr("id");
var idComplete = ('#' + idFind);
console.log(idComplete);
//TOGGLE FONT AWESOME ON CLICK
if ($(par).hasClass('selected')) {
par.find('.favorite i').toggleClass('fa-heart fa-heart-o');
} else {
par.find('.favorite i').toggleClass('fa-heart-o fa-heart');
};
if ($(par.hasClass('selected')) && ($('i').hasClass('fa-heart-o'))) {
par.closest('.selected').remove();
var getIcon = $(this).find('.favorite i').toggleClass('fa-heart-o fa-heart');
}
// Clone div
var add = $(this).parent().parent().parent();
add.each(function(){
if ($(add.find('.not-selected .favorite i').hasClass('fa-heart'))) {
var boxContent = $(add).clone(true, true);
var showHide = $(boxContent).find(".session").addClass('selected').removeClass('not-selected');
var get = $(boxContent).html();
var temp = localStorage.getItem('sessions');
var tempArray = [];
tempArray.push(get);
var myJSONString = JSON.stringify(tempArray);
var parseString = $.parseJSON(myJSONString);
var finalString = myJSONString.replace(/\r?\\n/g, '').replace(/\\/g, '').replace(/^\[(.+)\]$/,'$1').replace (/(^")|("$)/g, '');
var myJSONString = localStorage.setItem('sessions', finalString);
$("#fav").append(tempArray);
};
});
});
What I've tried..
var id = $(this).parents('.parent');
var idFind = id.attr("id");
var idComplete = ('#' + idFind);
if ($(par.hasClass('selected')) && ($('i').hasClass('fa-heart-o'))) {
par.closest('.selected').remove();
var getIcon = $(idComplete).find('.favorite i').toggleClass('fa-heart-o fa-heart');
}

jQuery: Why does it create two list items from one element

I have been trying to create a list within a specific div using jQuery that should be working as a menu that links to certain recipes within the page. Hence, the list is determined on the recipes in the html.
I have managed to create the id for each recipe and managed to create the list and the links. However, in the list the code creates two for each recipes and I have tried everything I can think about to fix it.
Here is the html code (I have not included everything due to the length):
<div id="primarycontent">
<div class="post">
<h4>
Potatis.
</h4>
<div class="contentarea">
<p>
...
</p>
</div>
</div>
<div class="post">
<h4>
Potatisbullar.
</h4>
<div class="contentarea">
<p>
...
</p>
</div>
</div>
<div class="post">
<h4>
Potatismos
</h4>
<div class="contentarea">
<p>
...
</p>
</div>
</div>
JS:
$(document).ready(generateMenu);
$(document).ready(addIdRecept);
function generateMenu()
{
var menyList = $("<ul></ul>");
$("#receptmeny").append(menyList);
$(".post h4:first-child").each(function(i)
{
var txt = $(this).closest(".post").find("h4").text();
var li = $("<li><li/>")
.appendTo(menyList);
var aLink = $("<a></a>")
.attr("href","#recept" + i)
.text(txt)
.appendTo(li);
});
}
function addIdRecept()
{
$(".post h4").each(function(i)
{
$(this).attr("id", "recept" + i);
});
}
This creates this list:
Potatis
Potatis
Potatisbullar
Potatisbullar
Potatismos
Potatismos
Why does it create two list items??
$(document).ready(generateMenu);
$(document).ready(addIdRecept);
function generateMenu() {
var menyList = $("<ul></ul>");
$("#receptmeny").append(menyList);
$(".post h4:first-child").each(function (i) {
txt = $(this).closest(".post").find("h4").text();
var li = $("<li></li>").appendTo(menyList);
var aLink = $("<a></a>").attr("href", "#recept" + i).text(txt).appendTo(li);
});
}
function addIdRecept() {
$(".post h4").each(function (i) {
$(this).attr("id", "recept" + i);
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="primarycontent">
<div class="post">
<h4>
Potatis.
</h4>
<div class="contentarea">
<p>
</p>
</div>
</div>
<div class="post">
<h4>
Potatisbullar.
</h4>
<div class="contentarea">
<p>
</p>
</div>
</div>
<div class="post">
<h4>
Potatismos
</h4>
<div class="contentarea">
<p>
</p>
</div>
</div>
</div>
<div id="receptmeny">
The reason is this line:
var li = $("<li><li/>").appendTo(menyList);
Modify the line to:
var li = $("<li></li>").appendTo(menyList);
Notice you are adding / after li instead of before it.
This is the funny and tricky question.
Please check the second line of jquery first function - var li = $("<li><li/>")
This should be - var li = $("<li></li>")
Then it will generate as you want.
Good luck

how to dynamically set text to an element in jquery

i have an onclick function that that calls a changeName function anytime a click event on that element happens.
function changeName() {
var frag = $('<span class="Name">change me</span>');
$( ".list" ).prepend(frag);
var x =[];
$('.ch-gname').each(function(index, obj)
{
x.push($(this).text());
for(i=0; i<x.length; i++) {
$('.Name').text(x[i]);}}});
$('#action').on('click', changeName);
HTML
<div>
<a href="#0" class="cb-pgcar"</a>
<span class="ch-gname">Greenhouse</span>
</div>
<div>
<a href="#0" class="cb-pgcar"</a>
<span class="ch-gname">tree house</span>
</div>
<div>
<a href="#0" class="cb-pgcar"</a>
<span class="ch-gname">light house</span>
</div>
<div class="list">
</div>
<div class="list">
</div>
<div class="list">
</div>
i want to able to change the text of the class Name to the text of class ch-gname. My function gives me only the last text text(lighthouse) for the three links.Any help please
The function changeName() has $('#action').on('click', changeName); but i do not see any element with id 'action'. Anyhow i've made necessary changes in order to make it work.
Added Action id to the elements
Changed the $('.Name').text(x[i]); to $('.Name')[i].innerHTML = x[i];
Look at the below example
function changeName() {
var frag = $('<span class="Name">change me</span>');
$(".list").prepend(frag);
var x = [];
$('.ch-gname').each(function(index, obj) {
x.push($(this).text());
});
for (i = 0; i < x.length; i++) {
$('.Name')[i].innerHTML = x[i];
}
}
$('#action').on('click', changeName);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<a href="#0" class="cb-pgcar" </a>
<span id="action" class="ch-gname">Greenhouse</span>
</div>
<div>
<a href="#0" class="cb-pgcar" </a>
<span id="action" class="ch-gname">tree house</span>
</div>
<div>
<a href="#0" class="cb-pgcar" </a>
<span id="action" class="ch-gname">light house</span>
</div>
<div class="list">
</div>
<div class="list">
</div>
<div class="list">
</div>

Categories