How to click to clone all id's that match these classes - javascript

I'm creating a page where I click a button and add content to a div. Right now I have three buttons that all have at least one class. Each class corresponds to a single div id that has its own content. What I'm trying to do is grab each class that is on the button, find the div id that has the same name, clone it, and append it to the #return div.
I have a working example that will only clone the first class name it sees on the button. How can I have my jquery find all div id's that match the classes on the button, clone them, and append them to #return?
These buttons can have the same class but when it's cloned in the #return, I don't want it cloned again. I have an if statement that tries to prevent this but it ends up deleting them. How can I stop this?
I have fiddle here that shows this jquery working:
$(document).ready(function() {
$("[id^=button]").click(function() {
var myclass = $(this).attr("class").split(" ");
if ($(this).is(".a1,.a2,.a3")) {
$("div#" + myclass).first().clone().appendTo("#return");
}
if ($("#return div#" + myclass).length > 1) {
$("#return div#" + myclass + ":last").remove();
}
});
});

The problem is that myclass is an array, so when you add that as a string to create a selector like "div#" + myclass it ends up creating a selector "div#a1,a2" which is not what you want.
You should iterate over the myclass array and perform your logic for each class.
Something like this
$(document).ready(function() {
$("[id^=button]").click(function() {
var myclass = $(this).attr("class").split(" ");
if ($(this).is(".a1,.a2,.a3")) {
myclass.forEach(function(currentClass) {
if ($("#return div#" + currentClass).length == 0)
$("div#" + currentClass).first().clone().appendTo("#return");
});
}
});
});
Updated demo at: https://jsfiddle.net/zyech6L3/2/

you need to iterate through to check what classes are available.
like:
for(var j=0; j<myclass.length; j++){
$("div#" + myclass[j]).first().clone().appendTo("#return");
}
see this fiddle:
https://jsfiddle.net/c4soamkr/

Related

Move array of DOM elements to placeholders in page

I have a design received on my page with a set of placeholders such as:
<span id="ApplicationDate_" class="removeMe"></span>
Plus other many elements as well inside that html. These spans should be replaced by real inputs coming from another area on the page, such inputs look like:
<input type="text" id="ApplicationDate_48596977"/>
So basically what I need to do, is to get all input elements in an array, and then for each element, get its ID up to "_", and search for the span that equals that value, and replace it with this element, then remove all spans with class=removeMe, but I can't achieve it in code, below is what I have reached:
$(document).ready(function () {
var coll = $("input");
coll.each(function () {
var id = this.id; //getting the id here
var substringId = id.substring(0, id.indexOf('_') + 1); //getting the span id
this.appendTo("#" + substringId); //having problems here..
});
$(".removeMe").each(function () {
this.remove();
});
});
it tells me this.appendTo is not a function, any help or hint is much appreciated.
TL;DR - Just use:
$(".removeMe").replaceWith(function() {
return $("input[id^='" + this.id + "']");
});
Here's why:
this is a DOM element, but .appendTo() is a jQuery method. You probably just need to wrap this in a call to jQuery:
$(this).appendTo("#" + substringId);
That would place the <input> element inside the <span> like this:
<span id="ApplicationDate_" class="removeMe">
<input type="text" id="ApplicationDate_48596977"/>
</span>
But, then you call:
$(".removeMe").each(function () {
this.remove();
});
First, you would have the same problem as above - this is a DOM element, but .remove() is a jQuery method. Second, it would be better to just call $(".removeMe").remove() - wrapping it in a .each() is redundant. Third, that would remove the span, and the input along with it. That's not what you are trying to do is it?
If you want to replace the span with the input, use .replaceWith():
var coll = $("input");
coll.each(function () {
var substringId = this.id.substring(0, id.indexOf('_') + 1);
$("#" + substringId).replaceWith(this);
});
It seems like the whole thing could be rewritten, taking advantage of the attribute starts with selector, as:
$(".removeMe").replaceWith(function() {
return $("input[id^='" + this.id + "']");
});

Sending a Static Value as a Parameter in an Event Listener

Using Javascript (and jQuery), I have an array of several objects. For each object in that array, I'm adding a small, clickable image to a div. Clicking each small image will change the path of a large image, thus showing a new picture.
Here's what I've got:
for (s = 0; s < splash.length; s += 1)
{
// add a new dot to this row
$(".splash_dots").append ("<div class = 'dot' id = 'dot" + s + "'><img src = 'images/dot2.png'></div>");
var id = 'dot' + s;
// add a click handler
document.getElementById (id).addEventListener ("click", function () {change_splash (s)});
}
//////////////////////////////////////////////////
function change_splash (s)
{
// load a new image for the large photo
$(".splash").attr ("src", splash[s].screenshot_link);
}
This almost works. The problem is that when change_splash() is called, I'm expecting the value of s to be what it was when the loop added the handler. For example, clicking the first dot will call change_splash(0). However, it's actually sending what s is when the click happens (after the loops ends, which is always array.length).
I have a temporary solution, but I don't like it::
if (s === 0) document.getElementById (id).addEventListener ("click", function () {change_splash (0)});
if (s === 1) document.getElementById (id).addEventListener ("click", function () {change_splash (1)});
This just seems really inefficient.
I'm basically just trying to create a sliding splash advertisement, like what you'd see on almost any retail homepage, so I know it's possible. Any ideas are appreciated.
Try with this
for (var s in splash){
// create the points, stores the id in the data-id attribute
$(".splash_dots").append ("<div class ='dot' data-id='" + s + "'><img src='images/dot2.png'></div>");
}
// click listener
$("body").on("click",".dot",function(){
// retrieve the id from the data-id attribute
var s = $(this).attr("data-id");
$(".splash").attr ("src", splash[s].screenshot_link);
});
See it in action in JSFiddle demo
you'll need a closure:
(function(id,s){
document.getElementById(id)
.addEventListener("click", function(){change_splash (s)});}(id,s));

Dynamically adding siblings and child elements using JavaScript/jQuery

I want a form that gives user the ability to dynamically add fields. What I need is the ability to add dynamic children and giving every child the ability to add its N number of children. Much like this
Parent 1
-- Child 1-1
-- Child 1-2
-- Child 1-2-1
-- Child 1-2-2
-- Child 1-2-3
-- Child 1-2-4
-- Child 1-2-4-1
-- Child 1-2-4-2
-- Child 1-3
-- Child 1-4
-- Child 1-5
-- Child 1-5-1
Parent 2
Parent 3
-- Child 3-1
Everything is dynamic, and a user can go as deep as they want to. So far, I'm able to achieve something similar to the JsFiddle link and I'm stuck badly after going 2 levels deep.
P.S: The numbers are added to show the relationship between a child to its siblings, its parent, and its children.
Update 1: This is what I've been able to achieve so far: JsFiddle
Update 2: Did some more work on this and was able to get it this far: jsFiddle
as discussed, i have worked it out on the fiddle.
please use the wrapElement() function to wrap your element in a div to your desire. In case you're loosing the fiddle, here's the code
$('.level_1').on('click', spawn);
function spawn(){
// check level
var level = stripLevel(this.className);
if (level !== '') {
var countOthers = this.parentNode.querySelectorAll("[class^='level_" + level +"']").length;
var x = wrapElement(level, countOthers);
if (level.length == 1) {
$('#addedElements').append(x);
} else {
//x.insertAfter(this);
$(this).parent().append(x);
}
}
}
// strip level
var stripLevel = function(className) {
var index = className.indexOf('_');
if(index > -1) {
return className.substr(index + 1);
} else {
return '';
}
}
// wrapper element
var wrapElement = function(level, number) {
var div = $('<div></div>');
if (level.length == 1) {
// it's parent
var input = $('<input type="text" name="foo_" />');
div.append(input);
} else {
// it's child
var span = $('<span>child level ' + level + '-' + number + '</span>');
div.append(span);
}
// add button
var button = $('<input class="level_' + level + '-' + number + '" type="button" value="Add Navigation" />');
button.on('click', spawn);
div.append(button);
div.css('margin-left', (level.length * 10) + 'px');
return div;
}
I wouldn't use the onclick attributes in html, but add the event handlers with javascrip
if your child nodes all use the same code, you could try to use a recursive approach:
function spawn(event) {
$(this).append(child);
$(child).on('click', function(event) {spawn(event);});
}
$('.parent').on('click', function(event) {spawn(event);});
was a first idea (with jquery), maybe it inspires you.
p.s. lacking the rep to make this comment, so it's an answer instead >.>
Based on the user3154108's answer, here's a recursive solution, you can start with:
$('.parent').on('click', spawn);
function spawn(){
var x = $('<input class="' + this.className + '-child" type="button" value="Add Navigation" />');
x.on('click', spawn);
x.insertAfter(this);
}
http://jsfiddle.net/Z9SBa/23/

Adding unique class name to dynamically created elements/ JS / jQuery

If I have ten divs created dynamically, each one given the class name 'createdDiv' on creation. How can I iterate through them after they are created and add a unique class name to each?
Somthing like,
for each('.createdDiv'){
var count = 1;
this.addClass('uniqueName' + count);
count ++;
}
So I would like to end up with 10 divs as follows,
('.createdDiv .uniqueName1')
('.createdDiv .uniqueName2')
('.createdDiv .uniqueName3')
('.createdDiv .uniqueName4')
and so on...
$('.createdDiv').each(function(i){
$(this).addClass('uniqueName' + i);
});
Try
$('.createdDiv').addClass(function (i) {
return 'uniqueName' + (i + 1)
})
Demo: Fiddle
$('.createDiv').each(function(i){
$(this).addClass('uniqueName'+ (i+1));
});
This is not exactly what you're asking for, but another way to later access a list of generated elements would be to use the data attribute:
$(".createDiv").each(function(i){
$(this).attr("data-index", i);
});
Then to select an element based on it's index:
$(".createDiv[data-index='" + i + "']")
Demo: Fiddle

Duplicate a span without Clone?

Hi I'm creating an ingredients app that has a form that looks like:
http://jsfiddle.net/PZjfT/
As you can see, there is a span containing 2 textfields, and a select. You can delete any span by clicking on the X next to it.
My problem is that I'm using jQuery Clone, so if you delete all of the spans, then click "Add Ingredient", there is no divs to clone, so it doesn't add an ingredient.
How could I fix this? Thanks for any and all help!
Use .detach() instead of .clone() for your last div, so you don't lose it.
.detach() will let you remove your last div from the DOM and save it in a variable, so you can later insert it again or clone from it.
Easy fix, clone the element on document ready but don't put it into the page and use that to clone.
jsFiddle
(function ($) {
$(document).ready(function () {
var myClone = $('#ingredientsCOUNT > span:first').clone();
$('#btnAddIngredients').click(function () {
var num = $('#ingredientsCOUNT span').length;
var newNum = new Number(num + 1);
myClone
.clone()
.attr('name', 'ingredient' + newNum)
.appendTo('#ingredientsCOUNT')
.fadeIn();
});
$('.formelementcontainer').on('click', '.deleteThis', function () {
var span = $(this).closest('span');
console.log(span);
span.fadeOut('slow', function () {
span.remove();
});
});
});
})(jQuery);
My approach would be that you don't let the user delete the last div.
So you always start out with one ingredient div on the page. Let them add new ones by cloning.
When the user removes an ingredient, delete the div and check how many ingredients are left. If it is only one, remove or hide the delete button, so they can't delete the last ingredient.

Categories

Resources