append element just after the one that was clicked - javascript

My eventListener doesn't work right. I would like to append an element newSlideDiv before the $( ".new-slide") which was clicked. How to make it correctly? Here is my wrong code.
Now the code appends newSlideDiv before every new slide button.
var newSlideButton = document.querySelectorAll('.new-slide');
for (var i = 0; i < newSlideButton.length; i++) {
newSlideButton[i].addEventListener('click', function(){
newSlide(); }, false )
}
var newSlide = function() {
var newSlideDiv = $('<div class="step slide">
<h2>New Slide</h2></div>');
$( ".new-slide").before(newSlideDiv);
}

Use this, which is the clicked element in the callback :
var newSlideButton = document.querySelectorAll('.new-slide');
for (var i = 0; i < newSlideButton.length; i++) {
newSlideButton[i].addEventListener('click', newSlide, false )
}
var newSlide = function() {
var newSlideDiv = $('<div class="step slide">
<h2>New Slide</h2></div>');
$(this).before(newSlideDiv);
}
But as you use jQuery, you don't need to use querySelectorAll :
$('.new-slide').click(function(){
var newSlideDiv = $('<div class="step slide"><h2>New Slide</h2></div>');
$(this).before(newSlideDiv);
});

You can try the following:
Assuming your HTML is something like this:
<div class="step slide new-slide">
<h2>New Slide 1</h2>
</div>
<div class="step slide new-slide">
<h2>New Slide 2</h2>
</div>
You can use this JS to add new elements and also give them the same behavior as the other divs:
var counter = 3; //Use to distinguish new added DIVs
var newSlide = function(e) {
//Create the elem to insert
var newSlideDiv = $('<div class="step slide"><h2 class="new-slide">New Slide '+ counter+'</h2></div>');
counter++;
//Insert it before the clicked element
$(e.target).before(newSlideDiv);
//Add the listener to have the same behavior
$(newSlideDiv).addEventListener('click',function(e) { newSlide(e);}, false );
}
//Initialize the DIV elems in the HTML with the listener
var newSlideButton = $('.new-slide');
for (var i = 0; i < newSlideButton.length; i++) {
newSlideButton[i].addEventListener('click',function(e) { newSlide(e);}, false )
}

Related

Nested Question Toggle using Radio Buttons

I have a relatively straightforward nested question setup using radio buttons and JavaScript/jQuery which shows/hides extra information based on the button that you click (Yes to show, No to hide):
Here is the HTML:
<div class="form-nest panel-question d-flex justify-content-start">
<span class="icon icon-primary icon-medium icon-roundel icon-vehicle align-self-start mr-2 mr-md-4"></span>
<div class="question-wrapper">
<h2 class="heading-epsilon">Are you interested in RAC Breakdown Cover for complete peace of mind?</h2>
<!-- Yes/no Open-->
<div class="form-row form-inline">
<div class="form-check form-check-inline"><input class="form-check-input form-check-input-button" type="radio" name="buttonRadio3" id="buttonRadio5"><label for="buttonRadio5">Yes</label></div>
<div class="form-check form-check-inline"><input class="form-check-input form-check-input-button" type="radio" name="buttonRadio3" id="buttonRadio6"><label for="buttonRadio6">No</label></div>
</div>
<!-- Yes/no closed -->
</div><!--question-wrapper-->
</div><!-- Form Nest Close-->
<!--Nested container open -->
<div class="nested-container">
<div id="buttonRadio5-nest" class="nested-content">
<ul class="list list-icons">
<li class="list-item list-icon list-icon-tick">Pays out regardless of whether the accident was fault or non-fault</li>
<li class="list-item list-icon list-icon-tick">Covers named drivers and passengers</li>
<li class="list-item list-icon list-icon-tick">Covers the policy holder when driving other vehicles if they don't own the vehicle</li>
</ul>
View more product information
<p><strong>+ £40.00</strong> per year</p>
<div class="form-row form-inline">
<div class="form-check form-check-inline"><input class="form-check-input form-check-input-button" type="checkbox" name="buttonCheckbox1" id="buttonCheckbox1"><label for="buttonCheckbox1">Add</label></div>
</div>
</div>
</div><!-- Nested container closed -->
And the JS/jQuery:
function nestedPanelHide(ele) {
var eleId = "#" + ele,
nestWrap = $(eleId).closest(".form-nest"),
nestCont = nestWrap.next(".nested-container");
nestCont.children().hide();
}
function nestedPanelShow(ele) {
var eleId = "#" + ele,
nestWrap = $(eleId).closest(".form-nest"),
nestCont = nestWrap.next(".nested-container"),
eleNestId = eleId + "-nest",
nestFields = nestCont.children(eleNestId);
nestedPanelHide(ele);
nestFields.show();
}
$(document).ready(function(){
$(".nested-content").hide();
// Find each form with nest class
$(".form-nest").each(function( index ) {
// Find nest conts
var nest = $(this),
nestCont = nest.next(".nested-container");
// For each nest cont
for (var i = 0; i < nestCont.length; i++) {
// Find nest opts in cont
var nestOpt = nestCont[i].children;
// For each nest opt add click event
for (var j = 0; j < nestOpt.length; j++) {
// Get cont id, trim to form ele id
var id = nestOpt[j].id,
str = id.substr(0, id.lastIndexOf("-")),
eleId = "#" + str;
// Add class to ele to remove from later look up
$(eleId).parent().addClass("nest-btn");
// Add show event listener to ele
$(eleId).on("click", function() {
var id = $(this).attr("id");
nestedPanelShow(id);
});
}
}
// Find nest opts
var nestOpts = nest.children();
// For each nest opt
for (var k = 0; k < nestOpts.length; k++) {
// Get this opt
var opt = $(nestOpts[k]);
// If opt does not have class nest-btn
if (!opt.hasClass("nest-btn")) {
// Add hide event listener to opt
$(opt.children()).on("click", function() {
var id = $(this).attr("id");
nestedPanelHide(id);
});
}
}
});
});
function nestedPanelHide(ele) {
var eleId = "#" + ele,
nestWrap = $(eleId).closest(".form-nest"),
nestCont = nestWrap.next(".nested-container");
nestCont.children().hide();
}
function nestedPanelShow(ele) {
var eleId = "#" + ele,
nestWrap = $(eleId).closest(".form-nest"),
nestCont = nestWrap.next(".nested-container"),
eleNestId = eleId + "-nest",
nestFields = nestCont.children(eleNestId);
nestedPanelHide(ele);
nestFields.show();
}
$(document).ready(function(){
$(".nested-content").hide();
// Find each form with nest class
$(".form-nest").each(function( index ) {
// Find nest conts
var nest = $(this),
nestCont = nest.next(".nested-container");
// For each nest cont
for (var i = 0; i < nestCont.length; i++) {
// Find nest opts in cont
var nestOpt = nestCont[i].children;
// For each nest opt add click event
for (var j = 0; j < nestOpt.length; j++) {
// Get cont id, trim to form ele id
var id = nestOpt[j].id,
str = id.substr(0, id.lastIndexOf("-")),
eleId = "#" + str;
// Add class to ele to remove from later look up
$(eleId).parent().addClass("nest-btn");
// Add show event listener to ele
$(eleId).on("click", function() {
var id = $(this).attr("id");
nestedPanelShow(id);
});
}
}
// Find nest opts
var nestOpts = nest.children();
// For each nest opt
for (var k = 0; k < nestOpts.length; k++) {
// Get this opt
var opt = $(nestOpts[k]);
// If opt does not have class nest-btn
if (!opt.hasClass("nest-btn")) {
// Add hide event listener to opt
$(opt.children()).on("click", function() {
var id = $(this).attr("id");
nestedPanelHide(id);
});
}
}
});
});
(function($) {
$('.label-yes').click(function() {
$(this).closest('.nested-content').addClass('open');
});
$('.label-no').click(function() {
$(this).closest('.nested-content').removeClass('open');
});
})(jQuery);
I can get the extra information to display when you click on "yes" but I can't get it to hide again when you click "no". I've tried going over line-by-line to see if I can identify where my error might be. I feel like it's something simple, but I fear I may have gone a little code blind from staring at it too much.
I have a JSfiddle here which shows you the basis of what I'm trying to achieve - I've stripped out the styling as it might give away who this is for (it's client work), but the basic functionality is there:
https://jsfiddle.net/3y4b25uk/
Any help or guidance that can be given would be greatly appreciated as I'm at the end of my tether trying to get it working and it's so nearly there.
Thank you.
Your code has a few issues - there are no elements with the classes label-yes and label-no, there is no class open, the selectors in the click() events for label-yes and label-no do not select the div with the class nested-content as this is not selectable with closest. The div with the class nested-conent is displayed upon click of "yes" not because of the click() event that is attached to label-yes, but because of a click() event you have earlier in your code in the $(".form-nest").each() function:
$(eleId).on("click", function() {
var id = $(this).attr("id");
nestedPanelShow(id);
});
To get the click() functions for label-yes and label-no working, I've added these classes to the input elements, added the class open, set the nested-content element to display:none via CSS and adjusted the selector in the click() events from
$(this).closest('.nested-content')
to
$(this).closest(".form-nest").next(".nested-container").find(".nested-content")
Working example:
function nestedPanelHide(ele) {
var eleId = "#" + ele,
nestWrap = $(eleId).closest(".form-nest"),
nestCont = nestWrap.next(".nested-container");
nestCont.children().hide();
}
function nestedPanelShow(ele) {
var eleId = "#" + ele,
nestWrap = $(eleId).closest(".form-nest"),
nestCont = nestWrap.next(".nested-container"),
eleNestId = eleId + "-nest",
nestFields = nestCont.children(eleNestId);
nestedPanelHide(ele);
nestFields.show();
}
$(document).ready(function() {
$(".nested-content").hide();
// Find each form with nest class
$(".form-nest").each(function(index) {
// Find nest conts
var nest = $(this),
nestCont = nest.next(".nested-container");
// For each nest cont
for (var i = 0; i < nestCont.length; i++) {
// Find nest opts in cont
var nestOpt = nestCont[i].children;
// For each nest opt add click event
for (var j = 0; j < nestOpt.length; j++) {
// Get cont id, trim to form ele id
var id = nestOpt[j].id,
str = id.substr(0, id.lastIndexOf("-")),
eleId = "#" + str;
// Add class to ele to remove from later look up
$(eleId).parent().addClass("nest-btn");
// Add show event listener to ele
$(eleId).on("click", function() {
var id = $(this).attr("id");
nestedPanelShow(id);
});
}
}
// Find nest opts
var nestOpts = nest.children();
// For each nest opt
for (var k = 0; k < nestOpts.length; k++) {
// Get this opt
var opt = $(nestOpts[k]);
// If opt does not have class nest-btn
if (!opt.hasClass("nest-btn")) {
// Add hide event listener to opt
$(opt.children()).on("click", function() {
var id = $(this).attr("id");
nestedPanelHide(id);
});
}
}
});
});
function nestedPanelHide(ele) {
var eleId = "#" + ele,
nestWrap = $(eleId).closest(".form-nest"),
nestCont = nestWrap.next(".nested-container");
nestCont.children().hide();
}
function nestedPanelShow(ele) {
var eleId = "#" + ele,
nestWrap = $(eleId).closest(".form-nest"),
nestCont = nestWrap.next(".nested-container"),
eleNestId = eleId + "-nest",
nestFields = nestCont.children(eleNestId);
nestedPanelHide(ele);
nestFields.show();
}
$(document).ready(function() {
$(".nested-content").hide();
// Find each form with nest class
$(".form-nest").each(function(index) {
// Find nest conts
var nest = $(this),
nestCont = nest.next(".nested-container");
// For each nest cont
for (var i = 0; i < nestCont.length; i++) {
// Find nest opts in cont
var nestOpt = nestCont[i].children;
// For each nest opt add click event
for (var j = 0; j < nestOpt.length; j++) {
// Get cont id, trim to form ele id
var id = nestOpt[j].id,
str = id.substr(0, id.lastIndexOf("-")),
eleId = "#" + str;
// Add class to ele to remove from later look up
$(eleId).parent().addClass("nest-btn");
// Add show event listener to ele
$(eleId).on("click", function() {
var id = $(this).attr("id");
nestedPanelShow(id);
});
}
}
// Find nest opts
var nestOpts = nest.children();
// For each nest opt
for (var k = 0; k < nestOpts.length; k++) {
// Get this opt
var opt = $(nestOpts[k]);
// If opt does not have class nest-btn
if (!opt.hasClass("nest-btn")) {
// Add hide event listener to opt
$(opt.children()).on("click", function() {
var id = $(this).attr("id");
nestedPanelHide(id);
});
}
}
});
});
(function($) {
$('.label-yes').click(function() {
$(this).closest(".form-nest").next(".nested-container").find(".nested-content").addClass("open");
});
$('.label-no').click(function() {
$(this).closest(".form-nest").next(".nested-container").find(".nested-content").removeClass("open");
});
})(jQuery);
.sandbox{
.panel-question{
display: flex;
flex-direction: row;
}
.form-row.form-inline {
width: 100%;
}
}
.nested-content {
display:none;
}
.open {
display:block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="sandbox">
<div class="container">
<div class="row">
<div class="col">
<div class="panel">
<div class="panel-content">
<div class="form-nest panel-question d-flex justify-content-start">
<span class="icon icon-primary icon-medium icon-roundel icon-vehicle align-self-start mr-2 mr-md-4"></span>
<div class="question-wrapper">
<h2 class="heading-epsilon">Are you interested in RAC Breakdown Cover for complete peace of mind?</h2>
<!-- Yes/no Open-->
<div class="form-row form-inline">
<div class="form-check form-check-inline"><input class="form-check-input form-check-input-button label-yes" type="radio" name="buttonRadio3" id="buttonRadio5"><label for="buttonRadio5">Yes</label></div>
<div class="form-check form-check-inline"><input class="form-check-input form-check-input-button label-no" type="radio" name="buttonRadio3" id="buttonRadio6"><label for="buttonRadio6">No</label></div>
</div>
<!-- Yes/no closed -->
</div>
<!--question-wrapper-->
</div><!-- Form Nest Close-->
<!--Nested container open -->
<div class="nested-container">
<div id="buttonRadio5-nest" class="nested-content">
<ul class="list list-icons">
<li class="list-item list-icon list-icon-tick">Pays out regardless of whether the accident was fault or non-fault</li>
<li class="list-item list-icon list-icon-tick">Covers named drivers and passengers</li>
<li class="list-item list-icon list-icon-tick">Covers the policy holder when driving other vehicles if they don't own the vehicle</li>
</ul>
View more product information
<p><strong>+ £40.00</strong> per year</p>
<div class="form-row form-inline">
<div class="form-check form-check-inline"><input class="form-check-input form-check-input-button" type="checkbox" name="buttonCheckbox1" id="buttonCheckbox1"><label for="buttonCheckbox1">Add</label></div>
</div>
</div>
</div><!-- Nested container closed -->
</div>
</div>
</div>
</div>
</div>
</section>
Note that the <div> with the class nested-content now gets displayed because of 2 reasons: once because of the working click() event handler on label-yes, and in addition because of the previous click() event that calls the function nestedPanelShow(). I'm not sure if you want to remove this click() event or rework your code so you're also attaching a click() event to the input for "No" and can omit the additional click() events you attach to label-yes and label-no. I've added a console message to this event handler in this Fiddle.

How to add ID to <a href> on click using JavaScript

I have an HTML like this
How add ID to HTML href with javascript
<div class="tab">
exp
</div>
<div class="tab">
exp
</div>
<div class="tab">
exp
</div>
<script>
var els = document.getElementsByClassName("tab");
// loops els
for(var i = 0, x = els.length; i < x; i++) {
els[i].onclick = function(){
x = document.querySelector(".tab> a")
// do something
x.id = "expid";
}
}
</script>
I want to add the id to each tag when I click this. Pls help me. Thks so much
<div class="tabs">
... your html code.
</div>
const tabs = document.querySelector('.tabs')
tabs.addEventListener('click', event => {
const aTag = event.target
if (aTag.tagName !== 'A') return
aTag.id = `EXPID#${getIndexIn(aTag, tabs)}`
})
function getIndexIn(element, parent): number
What's the meaning to be it?
Your call to document.querySelector() always returns the first .tab > a link in the document. You can this.querySelector() to return the link in the DIV that you clicked on instead.
I've changed the code to use a class rather than ID, since you shouldn't have duplicate IDs.
Loop through all the DIVs. If it's the DIV that the user clicked on, add the class, otherwise remove it.
var els = document.getElementsByClassName("tab");
// loops els
for (var i = 0, x = els.length; i < x; i++) {
els[i].onclick = function() {
for (var j = 0; j < els.length; j++) {
x = els[j].querySelector("a");
if (els[j] == this) {
x.classList.add("expid");
} else {
x.classList.remove("expid");
}
}
}
}
.expid {
background-color: yellow;
}
<div class="tab">
exp
</div>
<div class="tab">
exp
</div>
<div class="tab">
exp
</div>
const anchors = document.getElementsByTagName('a');
const ids= [1,2,3,4,5];
let index =0 ;
for(let a of anchors ){
a.href=ids[index++]
}
you can try this way it's a cool and easiest what I do with pure js

add element after all DIV tag using JavaScript

I wan't add element after every DIV tag, while 'i=0','i=1','i=2'...untill 'max-DIV.length'. What should I do? I'm just a little worry.. OH!
var NewSpan = document.createElement("span");
NewSpan.setAttribute("id", "gotop");
var NewSpanText = document.createTextNode("to be continue...");
NewSpan.appendChild(NewSpanText);
var i = 0;
var OldDiv = document.getElementsByTagName('div')[i];
var parent = OldDiv.parentNode;
if (parent.lastChild == OldDiv) {
parent.appendChild(NewSpan);
} else {
parent.insertBefore(NewSpan, OldDiv.nextSibling);
};
<div id="n1">DIV</div>
<div id="n2">DIV</div>
<div id="n3">DIV</div>
<div id="n4">DIV</div>
lile this
You need to wrap this in a for loop and create a new span element every time you want to insert one.
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
var NewSpan = document.createElement("span");
NewSpan.setAttribute("id", "gotop" + i); // Can't have duplicate IDs
var NewSpanText = document.createTextNode("to be continue...");
NewSpan.appendChild(NewSpanText);
var OldDiv = divs[i];
var parent = OldDiv.parentNode;
if (parent.lastChild == OldDiv) {
parent.appendChild(NewSpan);
} else {
parent.insertBefore(NewSpan, OldDiv.nextSibling);
}
}
<div id="n1">DIV</div>
<div id="n2">DIV</div>
<div id="n3">DIV</div>
<div id="n4">DIV</div>

Using jQuery to dynamically create checkboxes based on multiple attributes from div

I would like for jQuery to dyanmically create a list of checkboxes based on the class/data present in divs. Essentially these checkboxes will filter through the products so that clicking a checkbox will show the products containing that tag in their div while avoiding any duplicate checkboxes.
Sample:
<div class="Shoes" data-size="Small" data-color="Black">
<h3>Nike</h3>
</div>
<div class="Belts" data-size="Medium" data-color="Black">
<h3>Belt</h3>
</div>
<div class="Shirt" data-size="Large" data-color="Blue">
<h3>Polo</h3>
</div>
<div class="Socks" data-size="Small" data-color="White">
<h3>Generic Socks</h3>
</div>
Expected output
Class Type
Shoes
Belts
Shirt
Socks
Size
Small
Medium
Large
Color
Black
White
Blue
Each checkbox needs to be able to hide/show the item.
JsFIDDLE
The code I have so far is from searching around/previous answers, however it is only creating 1 checkbox type which is for "class" and not creating multiple ones.
Try
jQuery(function ($) {
function createCheckboxes($els, attr) {
var props = {};
$els.each(function () {
props[$(this).attr(attr)] = true;
});
return $.map(props, function (val, key) {
var $chk = $('<input />', {
type: 'checkbox',
value: key
})
return $('<label />', {
text: key
}).append($chk)
})
}
$('span').append(createCheckboxes($('div'), 'class'))
$('span').append(createCheckboxes($('div'), 'data-size'))
$('span').append(createCheckboxes($('div'), 'data-color'))
});
Demo: Fiddle
Try this http://jsfiddle.net/LzmTA/1/
HTML
<div class="Shoes" data-size="Small" data-color="Black">
<h3>Nike</h3>
</div>
<div class="Belts" data-size="Medium" data-color="Black">
<h3>Belt</h3>
</div>
<div class="Shirt" data-size="Large" data-color="Blue">
<h3>Polo</h3>
</div>
<div class="Socks" data-size="Small" data-color="White">
<h3>Generic Socks</h3>
</div>
Javascript
$(document).ready(function(){
var goods = {};
var divs = $('div');
for(var i = 0; i < divs.length; i++){
var attributes = divs[i].attributes;
var item = {};
for(var j = 0; j < attributes.length; j++){
var attrName = attributes[j].name;
if(!goods[attrName]){
goods[attrName] = {};
}
goods[attrName][attributes[j].value] = 1;
}
}
printAttributes(goods);
console.log(goods);
});
function printAttributes(goods){
for(var group in goods){
var groupTitle = $('<h3>').text(group);
$('span').append(groupTitle);
for(var item in goods[group]){
console.log(item);
var sp = $('<label>').text(item);
var chk = $('<input>').attr('type', 'checkbox').attr('value', item).attr('attr', group);
chk.bind('change', function(){
filterGoods();
});
$('span').append(chk).append(sp);
}
}
}
function filterGoods(){
var separator = '|';
var chks = $('input[type=checkbox]:checked');
var filter = [];
//get filter
for(var i = 0; i < chks.length; i++){
var item = $(chks[i]).attr('attr') + separator + $(chks[i]).val();
filter.push(item);
}
//do filter
var hasAttr = false;
var divs = $('div');
for(var i = 0; i < divs.length; i++){
hasAttr = false;
for(var j = 0; j < filter.length; j++){
var filterParts = filter[j].split(separator);
if($(divs[i]).attr(filterParts[0]) == filterParts[1]){
hasAttr = true;
continue;
}
}
hasAttr ? $(divs[i]).show() : $(divs[i]).hide();
}
console.log(filter);
}

How to fill a div with content under the condition that the div has no childs?

For example, when I have:
<div class="abc123"></div> <!-- no child div -->
I want to insert a new div in it:
<div class="xyz">some content</div>
So that the outcome is:
<div class="abc123">
<div class="abc">Some Content</div>
</div>
How can I implement this using javascript?
in jQuery:
$(".abc123").each(function() {
if (this.children(".abc").length == 0) {
$(this).append('<div class="xyz">some content</div>');
}
});​
in Simple JS
var divs = document.getElementsByTagName("div");
for (var i = 0; i < divs.length; i++) {
if (divs[i].childNodes.length == 0) { // testing if it has not child
var newdiv = document.createElement('div');
newdiv.innerHTML = "some content";
newdiv.className = "xyz";
divs[i].appendChild(newdiv);
}
}​
Edit:
This following piece of code produces the same effect as done in the above mentioned jQuery code(edited in light of the comment by RobW ):
var divs = document.getElementsByClassName("abc123");
for (var i = 0; i < divs.length; i++) {
if (divs[i].getElementsByClassName("abc").length == 0) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "some content";
newdiv.className = "xyz";
divs[i].appendChild(newdiv);
}
}​
Maybe you would like to take a look at this question: How to check if element has any children in Javascript?
Seems like what you are looking for :)
With jQuery:
if ($('.abc123 div').length == 0) {
$('.abc123').append('<div class="xyz">some content</div>');
}​

Categories