Jquery .clone() only works once - javascript

I'm building a menu ordering app where I have to use Jquery.
I'm using the clone() method to duplicate cart items with the necessary data ejected in. It works once, and then logs and empty object with a <prototype>.
What I am cloning is a section in my HTML I am using as a template with an id to keep it hidden. I remove this on the cloned items.
The ejecting of the data I have excluded as it is working fine and the functions are in other files, but I am open to the idea of them being the cause.
HTML:
<div class="cart-item" id="cartitem-template">
<div class="left">
<div class="image"></div>
<div class="price"></div>
</div>
<div class="mid">
<div class="name">
</div>
<div class="stars">
<span></span>
</div>
<div class="underline"></div>
<div class="toggleReviews">
<span></span>
</div>
</div>
<div class="right">
<div class="remove-cart-item">✕</div>
</div>
</div>
</div>
The JS function:
buildCartItem = function(menuItem) {
const template = $("#cartitem-template")
template
.removeAttr("id")
.clone(false)
const newCartItem = template
newCartItem.insertAfter(".cart-item")
console.log(newCartItem)
//Get object and index atts from clicked menu item
//Also set that same data into the dom of the cart item
//As well as set that data to local storage
...
// Apply data to the cloned cart item template
newCartItem.find(".image").css("background-image", "url(" + data.image + ")")
setData(".price", "$"+data.price, newCartItem)
...
}
$(".menu-item").click(function() {
buildCartItem($(this))
})
I'm I using .clone() correctly? Honestly stuck

You are removing the attribute "id" from the source element even before cloning, That's why in the subsequent method invocations it could not find an element with the id "cartitem-template". So in your method buildCartItem, remove "id" after cloning.
const newCartItem = template.clone(false).removeAttr("id");

var buildCartItem = function(menuItem) {
const newCartItem = $("#cartitem-template").clone(false).removeAttr("id");
//newCartItem.find(".image").css("background-image", "url(" + data.image + ")");
//setData(".price", "$" + data.price, newCartItem);
newCartItem.insertAfter("#cartitem-template");
}
$(".menu-item").click(function() {
buildCartItem($(this))
})
#cartitem-template {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cart-item" id="cartitem-template">
<div class="left">
<div class="image">image</div>
<div class="price">price</div>
</div>
<div class="mid">
<div class="name">name
</div>
<div class="stars">
<span>0</span>
</div>
<div class="underline"></div>
<div class="toggleReviews">
<span></span>
</div>
</div>
<div class="right">
<div class="remove-cart-item">✕</div>
</div>
</div>
<button class="menu-item">Clone</button>

i had similar problem and i solved using function:
function getClone(){
return $(myCloningDiv).clone()
}

Related

How to add and remove class dynamically to child div based on value in Jquery

if data value is matching with any div inside requestsampler class then dynamically add new class(sampleClass) to test class inside the matching container
js:
var data = **somevalue**;
data is dynamic value
html:
<div class="requestsampler">
<div class= "**somevalue**">
<div class="test"> // add new class <div class="test sample class">
//
</div>
</div>
<div class= "somevalue2">
<div class="test">
//
</div>
</div>
<div class= "somevalue3">
<div class="test">
//
</div>
</div>
</div>
tried not working:
$('.requestsampler').hasClass(data) {
$(.'requestsampler .`${data}` .test').addClass('sampleclass');
}
You could simply use Attribute Contains Prefix Selector [name|="value"] for more info please refer http://jqapi.com/#p=attribute-contains-prefix-selector.. below is the code for your example.
$(document).ready(()=>{
var data = "somevalue"; $('div[class|="'+data+'"]>.test').addClass("sampleclass");
})
.sampleclass{
background-color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="requestsampler">
<div class= "somevalue">
<div class="test"> // add new class <div class="test sample class">
//
</div>
</div>
<div class= "somevalue2">
<div class="test">
//
</div>
</div>
<div class= "somevalue3">
<div class="test">
//
</div>
</div>
</div>
you could try jquery elem.find() api. And also use className with string and numeric combination instead of symbols
i have changed the condition with element find length. Because hasClass() only perform on the selector element. So if you are using find() they will find the matched element.
And also your if condition does not make any sense, without condition is also working same
Updated
If you need first test element. use .eq(0) or else use different className for the first test element
var data = "somevalue";
if ($('.requestsampler').find(`.${data}`).length > 0) {
$('.requestsampler').find(`.${data}`).find('.test').eq(0).addClass('sampleclass');
}
.sampleclass {
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="requestsampler">
<div class="somevalue">
<div class="test"> // add new class
<div class="test sample class">
sample
</div>
</div>
<div class="somevalue2">
<div class="test">
//
</div>
</div>
<div class="somevalue3">
<div class="test">
//
</div>
</div>
</div>

How to detach and append to relevant div only jQuery

I am trying to detach the div from the relevant parent and then append to the same parent div.
//Jquery Code
jQuery(function(){
moveColorDots();
});
function moveColorDots(){
var copyDivData = jQuery('.variations_form.wvs-archive-variation-wrapper').detach();
copyDivData.appendTo('.product-variations');
}
<div class="pp-content-post">
<div class="variations_form wvs-archive-variation-wrapper">
some data here
</div>
<div class="product-box">
<div class="glasses-sec">
<h3>title</h3>
</div>
<div class="product-variations"></div>
</div>
</div>
Expected result.
But after running the above code I am getting the following result.
.detach Description: Remove the set of matched elements from the DOM.
That means you append all the detached elements to every product-variations element ..So
You need to loop through the variations_form.wvs-archive-variation-wrapper elements by using .each()
Also you can use .appendTo() directly
//Jquery Code
jQuery(function(){
moveColorDots();
});
function moveColorDots(){
jQuery('.variations_form.wvs-archive-variation-wrapper').each(function(){
var product_variations = jQuery(this).next('div').find('.product-variations');
jQuery(this).appendTo(product_variations);
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="pp-content-post">
<div class="variations_form wvs-archive-variation-wrapper">
some data here 1
</div>
<div class="product-box">
<div class="glasses-sec">
<h3>title</h3>
</div>
<div class="product-variations"></div>
</div>
</div>
<div class="pp-content-post">
<div class="variations_form wvs-archive-variation-wrapper">
some data here 2
</div>
<div class="product-box">
<div class="glasses-sec">
<h3>title</h3>
</div>
<div class="product-variations"></div>
</div>
</div>
Note: This line of code var product_variations = jQuery(this).next('div').find('.product-variations'); is depending on your html structure it works for the posted html here .. But if you've another html structure you need to modify it to catch the desired element

Link simillary name classes so that when one is clicked the other is given a class

Basically, I'm asking for a way to optimize this code. I'd like to cut it down to a few lines because it does the same thing for every click bind.
$("#arch-of-triumph-button").click(function(){
$("#arch-of-triumph-info").addClass("active-info")
});
$("#romanian-athenaeum-button").click(function(){
$("#romanian-athenaeum-info").addClass("active-info")
});
$("#palace-of-parliament-button").click(function(){
$("#palace-of-parliament-info").addClass("active-info")
});
Is there a way to maybe store "arch-of-triumph", "romanian-athenaeum", "palace-of-parliament" into an array and pull them out into a click bind? I'm thinking some concatenation maybe?
$("+landmarkName+-button").click(function(){
$("+landmarkName+-info").addClass("active-info")
});
Is something like this even possible?
Thanks in advance for all your answers.
EDIT: Here's the full HTML.
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Arch of Triumph</span>
</div>
<div class="landmark-button" id="arch-of-triumph-button"></div>
</div>
</div>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Romanian Athenaeum</span>
</div>
<div class="landmark-button" id="romanian-athenaeum-button"></div>
</div>
</div>
----------------------------------------------------------
<div class="landmarks-info-wrapper">
<div class="landmark-info" id="arch-of-triumph-info">
<div class="info-landmark section">
<span class="landmark-title">Arch of Triumph</span>
<span class="landmark-coord">44°28′1.99″N 26°4′41.06″E</span>
</div>
</div>
<div class="landmark-info" id="romanian-athenaeum-info">
<div class="info-landmark section">
<span class="landmark-title">The Romanian Athenaeum</span>
<span class="landmark-coord">44.4413°N 26.0973°E</span>
</div>
</div>
Assuming you're not able to modify your HTML markup (in which case with use of CSS classes would be cleaner), a solution to your question would be as shown below:
// Assign same click handler to all buttons
$("#arch-of-triumph-button, #romanian-athenaeum-button, #palace-of-parliament-button")
.click(function() {
// Extract id of clicked button
const id = $(this).attr("id");
// Obtain corresponding info selector from clicked button id by replacing
// last occurrence of "button" pattern with info.
const infoSelector = "#" + id.replace(/button$/gi, "info");
// Add active-info class to selected info element
$(infoSelector).addClass("active-info");
});
Because each .landmark-button looks to be in the same order as its related .landmark-info, you can put both collections into an array, and then when one is clicked, just find the element with the same index in the other array:
const buttons = [...$('.landmark-button')];
const infos = [...$('.landmark-info')];
$(".landmark-button").click(function() {
const i = buttons.indexOf(this);
$(infos[i]).addClass('active-info');
});
This does not rely on IDs at all - feel free to completely remove those from your HTML to declutter, because they don't serve any purpose now that they aren't being used as selectors.
Live snippet:
const buttons = [...$('.landmark-button')];
const infos = [...$('.landmark-info')];
$(".landmark-button").click(function() {
const i = buttons.indexOf(this);
$(infos[i]).addClass('active-info');
});
.active-info {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Arch of Triumph</span>
</div>
<div class="landmark-button" id="arch-of-triumph-button">click</div>
</div>
</div>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Romanian Athenaeum</span>
</div>
<div class="landmark-button" id="romanian-athenaeum-button">click</div>
</div>
</div>
----------------------------------------------------------
<div class="landmarks-info-wrapper">
<div class="landmark-info" id="arch-of-triumph-info">
<div class="info-landmark section">
<span class="landmark-title">Arch of Triumph</span>
<span class="landmark-coord">44°28′1.99″N 26°4′41.06″E</span>
</div>
</div>
<div class="landmark-info" id="romanian-athenaeum-info">
<div class="info-landmark section">
<span class="landmark-title">The Romanian Athenaeum</span>
<span class="landmark-coord">44.4413°N 26.0973°E</span>
</div>
</div>
Older answer, without knowing the HTML: You can extract the ID of the clicked button, slice off the button part of it, and then select it concatenated with -info:
$(".landmark-button").click(function() {
const infoSel = this.id.slice(0, this.id.length - 6) + 'info';
$(infoSel).addClass('active-info');
});
A much more elegant solution would probably be possible given the HTML, though.

How to get the attribute value of the closest element

Here i have HTML structure and the same structure may repeat number of times with the same class names. what i'm trying to do is once i click on the .innerDiv i should be able to access the attr value of the .inid close to its parent element.
here is what i have tried, but its not working. i also tried adding the classname to the element i'm trying to get the value from. but its adding the class to all the element with .inid. how can i do this?
HTML
<div class="parent_div">
<div class="content-container">
<div class="second-most-innerdiv>
<div class="container-box">
<div class="innerDiv">Click here</div>
</div>
</div>
</div>
<div class="inid" data-attr="jkoadoas-Kjksjfks_skaj"></div>
</div>
<div class="parent_div">
<div class="content-container">
<div class="second-most-innerdiv>
<div class="container-box">
<div class="innerDiv">Click here</div>
</div>
</div>
</div>
<div class="inid" data-attr="jkoadoas-Kjksjfks_skaj"></div>
</div>
Jquery
$(this).on('click',function(){
$('.innerDiv').parents().find('.inid').addClass('testclass');
$('.innerDiv').parents().find('.inid').attr(data-attr);
});
To achieve expected result, use index of innerDiv and add class-testclass to element with class- inid
Find index of clicked innerDiv using index('.innerDiv)
Use that index to add class using eq
Add some sample css to testclass for testing
Syntax error in your code - closing quotes missing for class- second-most-innerdiv
Codepen - https://codepen.io/nagasai/pen/
working example
$('.innerDiv').on('click',function(){
$('.inid').eq($(this).index('.innerDiv')).addClass('testclass');
console.log($('.inid').eq($(this).index('.innerDiv')).attr('data-attr'))
});
.testclass{
background: red;
height: 10px;
width:10px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent_div">
<div class="content-container">
<div class="second-most-innerdiv">
<div class="container-box">
<div class="innerDiv">Click here</div>
</div>
</div>
</div>
<div class="inid" data-attr="jkoadoas-Kjksjfks_skaj"></div>
</div>
<div class="parent_div">
<div class="content-container">
<div class="second-most-innerdiv>
<div class="container-box">
<div class="innerDiv">Click here</div>
</div>
</div>
</div>
<div class="inid" data-attr="jkoadoas-Kjksjfks_skaj"></div>
</div>
Using JQuery closest() feature to find the parent div, then find the element with class "inid" within that parent element and get the value of the attribute.
$('.innerDiv').on('click',function(){
var inid = $(this).closest('.parent_div').find('.inid');
inid.addClass('testclass');
console.log('selected -> ' + inid.attr(data-attr));
});
Source: https://api.jquery.com/closest/

Generate link based on data attributes

I am trying to write a little jQuery script that checks a set of div's to see if they have a data-name attribute. For the ones that have a data-name, it will create a link. The href of that link should be the name of the data-value plus contain the file extension (eg. .txt).
Everything seems to work OK except when I try to add the data value onto the link. The ultimate result of this script is to output something like this for each of those div's:
<p class="data-link">Edit
Below is my script. I have identified that area that I am having issue with.
var dataNameWrappers = $("div#desktopSidebar div[data-name]");
dataNameWrappers.each(function() {
var dataNameWrappers_action = "" + $(this).attr("data-name");
$(this).prepend("<p class='edit-link'><a>Edit</a></p>");
var dataNameWrapperEditLink = $("div#desktopSidebar p.edit-link a");
dataNameWrapperEditLink.each(function() {
$(this).attr('href', <<stuck_here>>);
});
});
Any help will be great.
Thanks
As requested, here is my sidebar HTMl structure
<div id="desktopSidebar">
<div class="sidebar userbox">
<h3 class="sidebarheader"> Welcome {{username}}}</h3>
</div>
<div data-name="social_media_sitewide" class="sidebar socialmedia">
<h3 class="sidebarheader">Follow Tennis-Chat</h3>
</div>
<div data-name="site_promotions" class="sidebar promotions">
<h3 class="sidebarheader">Current Promotions</h3>
</div>
<div data-name="livescores" class="sidebar Livescores">
<h3 class="sidebarheader">Live Scores</h3>
</div>
<div class="sidebar tournaments">
<h3 class="sidebarheader">Tournaments</h3>
</div>
<div data-name="featured-profiles" class="sidebar profiles">
<h3 class="sidebarheader">Today's Profile: {{featured_profile_name}}</h3>
</div>
<div data-name="side_advertisment" class="sidebar Advertisement">
<h3 class="sidebarheader">Advertisement</h3>
</div>
<div class="sidebar Headlines">
<h3 class="sidebarheader">Tennis-Chat Headlines</h3>
</div>
<div class="sidebar mostrecent" id="mostRecentTopics">
<h3 class="sidebarheader">Most Recent Posts</h3>
</div>
</div>
I don't know why you are using a second loop to add the HREFs when you already have everything you need.
Working fiddle here: http://jsfiddle.net/Q4j8S/.
HTML:
<div id="desktopSidebar">
<div class="sidebar userbox">
<h3 class="sidebarheader"> Welcome {{username}}}</h3>
</div>
<div data-name="social_media_sitewide" class="sidebar socialmedia">
<h3 class="sidebarheader">Follow Tennis-Chat</h3>
</div>
<div data-name="site_promotions" class="sidebar promotions">
<h3 class="sidebarheader">Current Promotions</h3>
</div>
<div data-name="livescores" class="sidebar Livescores">
<h3 class="sidebarheader">Live Scores</h3>
</div>
<div class="sidebar tournaments">
<h3 class="sidebarheader">Tournaments</h3>
</div>
<div data-name="featured-profiles" class="sidebar profiles">
<h3 class="sidebarheader">Today's Profile: {{featured_profile_name}}</h3>
</div>
<div data-name="side_advertisment" class="sidebar Advertisement">
<h3 class="sidebarheader">Advertisement</h3>
</div>
<div class="sidebar Headlines">
<h3 class="sidebarheader">Tennis-Chat Headlines</h3>
</div>
<div class="sidebar mostrecent" id="mostRecentTopics">
<h3 class="sidebarheader">Most Recent Posts</h3>
</div>
</div>
JavaScript:
var dataNameWrappers = $("div#desktopSidebar div[data-name]");
dataNameWrappers.each(function() {
var dataNameWrappers_action = $(this).attr("data-name");
console.log('data-name ' + dataNameWrappers_action);
$(this).prepend('<p class="edit-link">Edit</p>');
/* Don't need this
var dataNameWrapperEditLink = $("div#desktopSidebar p.edit-link a");
dataNameWrapperEditLink.each(function() {
$(this).attr('href', dataNameWrappers_action);
});
*/
});
Instead of iterating through the a tags after you do the prepend, it may be better to make the HTML fragment with the desired href attribute.
Here is the code that accomplishes that:
$('#desktopSidebar .sidebar[data-name]').each(function(index, el){
var href = $(el).attr('data-name') + ".txt";
$(el).prepend('<p class="edit-link">Edit');
});

Categories

Resources