jQuery | detach(), append() scope - javascript

I have a main-div and two divs with the class of container. The div with the class of container has a child div with a class of content with different contents. I'd like for the user to click on their choice of containers and transport its content to main-div. Then when the user clicks on the main-div, I'd like to transport that content back to its original div.
I'm not sure how to detach the content from main-div once it's been passed and reinsert it back into its original parent. I would appreciate any help.
I can't use IDs. I can only uses classes.
HTML
<div class="main-div">
</div>
<div class="container">
<div class="contents">
A
</div>
</div>
<div class="container">
<div class="contents">
B
</div>
</div>
CSS
.main-div {
width: 100wv;
height: 200px;
background: yellow;
cursor: pointer;
}
.container {
width: 40vw;
height: 150px;
border: 2px solid purple;
display: inline-block;
}
.contents {
width: 50px;
height: 50px;
background: green;
}
JS
$('.container').click(function() {
var child = $(this).children();
console.log('child ' + child);
$('.main-div').append(child);
});
$('.main-div').click(function(child) {
console.log('child ' + child);
$('.main-div').detach(child);
});
FIDDLE

Set ids for the containers
<div class="main-div">
</div>
<div class="container" id="container1">
<div class="contents">
A
</div>
</div>
<div class="container" id="container2">
<div class="contents">
B
</div>
</div>
And set a data attribute for the children on click to identify the parent element.
$(function() {
$('.container').click(function() {
var child = $(this).children();
child.attr("data-parentcontainer", this.id);
$('.main-div').append(child);
});
$('.main-div').click(function(child) {
var child = $(this).children();
child.appendTo($("#" + child.data("parentcontainer")));
});
});
JSFIDDLE

Use this JS snippet and let me know if it helps
$('.container').click(function() {
console.log('foo');
var child = $(this).html();
console.log(child);
$('.main-div').append(child);
});
$('.main-div').click(function() {
console.log('foo');
var main = $(this).html();
if(main.length != 0) {
$('.main-div').empty();
}
else
console.log('Main div is empty');
});

External DEMO
You can use .detach() and .appendTo(), but along with that you have to keep some identification to know from that .contents div was picked up. So I am making use of data-address attribute for the parent of picked .contents so as to attach it back there. See inline comments for detailed explanation on what will happen with the code.
$('.main-div').on('click', function(e) {
var elem = $(e.target); //capture click event on .main-div
if (elem.hasClass('contents')) { //check if click was on .contents div
var text = elem.text().trim(); //if yes then get its text
elem.detach();//detach the element
elem.appendTo($('div[data-address=' + text + ']')); //attach it based on attribute selector of jquery
}
});
$('.contents').on('click', function() {
var elem = $(this);//get the element
elem.closest('.container').attr('data-address', elem.text().trim())
//add or update data-address attribute of its closest parent i.e. .container
elem.detach();//detach the element
elem.appendTo($('.main-div')); //append it to .main-div
})
.main-div {
width: 200px;
height: 200px;
background: yellow;
cursor: pointer;
}
.container {
width: 150px;
height: 150px;
border: 2px solid purple;
}
.contents {
width: 50px;
height: 50px;
background: green;
position: relative;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main-div">
</div>
<div class="container">
<div class="contents">
A
</div>
</div>
<div class="container">
<div class="contents">
B
</div>
</div>

You need to add some uniqueness on the div that have class container, you can add a class or id so that when reinserting back to the original div we can identify the div.
i don't think is there other solution to reinsert back to the original div, whenever we identify both div uniquely.
please change your html structure so that we can manipulate through jquery.

Related

Is it possible to call classes of nested divs with JS/Jquery?

I am unable to find this anywhere...Just wondering if it's possible to call nested divs and place them in one function? For example:
<div class="a">
<div class="b-1"></div>
<div class="b-2"></div>
</div>
How do I call them together as a function to update their styles?
Edit: I might not be too clear here. What I am trying to ask is... For example:
.a {
background-color: black; width:200px; height: 200px; position: relative; }
.b-1 { color: white;
position: absolute;}
.b-2 {color: white;
position: absolute; padding-top: 20px; }
<div class="a">
<div class="b-1"> test b1</div>
<div class="b-2"> test b2</div>
</div>
Is it possible to update a, b-1, b-2 classes in one function?
So the result is:
function updateMultipleClasses() {
change a to grey
change b1 and b2 to red
}
I would like to be able to just call this function instead. is this possible?
You can use jquery wild card selector
$("div[class^='b-']").addClass('test')
.test {
color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="a">
<div class="b-1">B-1</div>
<div class="b-2">B-2</div>
</div>
You can pass the NodeList by using querySelectorAll to your function that will select both parent and all children div elements and then use forEach loop on that selector.
function updateStyles(els) {
els.forEach(e => {
e.style.border = '1px solid red'
if (e.classList.contains('a')) {
e.style.backgroundColor = 'green'
}
if ([...e.classList].some(cls => ['b-1', 'b-2'].includes(cls))) {
e.style.backgroundColor = 'white'
}
})
}
updateStyles(document.querySelectorAll('.a, .a div'))
* {
padding: 5px
}
<div class="a">
<div class="b-1">1</div>
<div class="b-2">
<div class="b-3">3</div>
</div>
</div>
Don't use JS to style.
Use JS only to add a class to the .a Element, than use CSS to define the styles that should be applied to the ancestor and its children.
const makeSelected = (EL) => {
EL.classList.add("selected");
};
document.querySelectorAll(".a").forEach(makeSelected);
.a.selected {
color: gold;
}
.a.selected [class^="b-"],
.a.selected [class*=" b-"]{
color: fuchsia;
}
<div class="a">
a a a a a
<div class="b-1">b 1 1 1 1</div>
<div class="b-2">b 2 2 2 2</div>
</div>

How To Get All Text Content from Duplicate Parent Class with Different Id?

I am trying to get all text content of a parent class detected by addEventListener.
The code I am using is-
document.addEventListener('click',function (event) {
var text = document.getElementsByClassName(event.target.parentElement.parentElement.parentElement.className);
console.log(text[0].innerText);
}, false);
but the problem is, where I am trying to apply the code, has same class name with different id, for example-
<div class="sc-EHOje gMuVTh" size="24" role="group" aria-labelledby="extraTitle_70356820.0">
and
<div class="sc-EHOje gMuVTh" size="24" role="group" aria-labelledby="extraTitle_70356820.1">
has same ClassName (sc-EHOje gMuVTh) but different id (extraTitle_70356820.1 and extraTitle_70356820.0), so if I use only ClassName I always get text for id extraTitle_70356820.0, even if I click for extraTitle_70356820.1.
How can I get all text from the class of the id I clicked when there is duplicate class name? Is there a way to incorporate the ClassName and id at the same time to get the text from parent?
I changed my initial answer because I realised I think you want the uppermost parent text too as well as the text of the element you clicked on? Not sure if this answer is the correct for you but it's my take on things.
//var classname = document.getElementsByClassName("sc-EHOje gMuVTh");
//for (var i = 0; i < classname.length; i++) {
// classname[i].addEventListener('click', function() {
// console.log(this.parentElement.parentElement.parentElement.innerText);
// });
//}
// 24/09 edit
var target = "sc-EHOje gMuVTh";
document.addEventListener('click', function(event) {
if (event.target.className === target) {
var parentElemText = event.target.parentElement.parentElement.parentElement.innerText;
console.log(parentElemText);
}
});
.upperMostParent {
width: 200px;
height: 200px;
background: red;
margin: 1rem;
position: relative;
}
.secondUpper {
width: 100px;
height: 100px;
background: blue;
margin: 1rem;
padding: 1rem;
}
.thirdUpper {
width: 70px;
height: 50px;
background: green;
padding: 1rem;
}
.sc-EHOje.gMuVTh {
background: yellow;
width: 50px;
height: 50px;
}
<div class="upperMostParent">
Parent text content 1
<div class="secondUpper">
<div class="thirdUpper">
<div class="sc-EHOje gMuVTh" size="24" role="group" aria-labelledby="extraTitle_70356820.0">Some text content</div>
</div>
</div>
</div>
<div class="upperMostParent">
Parent text content 2
<div class="secondUpper">
<div class="thirdUpper">
<div class="sc-EHOje gMuVTh" size="24" role="group" aria-labelledby="extraTitle_70356820.1">Some more text</div>
</div>
</div>
</div>

How to apply a function that affects the parent of each element with a certain class name?

I have a series of divs with the class name x that are inside of other divs with the class name item. The item divs are inside a section of the main.
What I want to do is create a function that applies equally to every x class div by affecting their respective parent (in this case changing their CSS).
I coded this:
var openbtn = document.getElementsByClassName("x")[0];
openbtn.onclick = function() {
document.body.parentElement.style.backgroundColor = "red";
}
However, this only works on the first x class <div>. When it works, it changes the background color of the section, or main or body element, and not the x class div parent (the item class div).
If you want to handle this with a handler on each .x element, you have to add a handler to each .x element. (But you may not want to do that, keep reading.) That would look like this:
var openbtns = document.getElementsByClassName("x");
for (var n = 0; n < openbtns.length; ++n) {
openbtns[n].addEventListener("click", xClickHandler);
}
...where xClickHandler uses this (or event.currentTarget) to know which .x element was clicked:
function xClickHandler() {
this.parentElement.style.backgroundColor = "red"; // I suggest using a class instead of doing this, btw
}
But, if all of these .x elements are within the same overall container, you can do it with event delegation, like this:
document.querySelector("selector-for-the-overall-container").addEventListener("click", function(event) {
// Find the `.x` that was clicked (which may be `event.target` or may be
// an ancestor node of it
var x = event.target.closest(".x");
if (x && this.contains(x)) {
x.parentElement.style.backgroundColor = "red"; // Again, suggest using a class
}
});
More:
closest
contains
Live Example using the HTML from your comment:
document.getElementById("items").addEventListener("click", function(event) {
// Find the `.x` that was clicked (which may be `event.target` or may be
// an ancestor node of it
var x = event.target.closest(".x");
if (x && this.contains(x)) {
x.parentElement.style.backgroundColor = "red"; // Again, suggest using a class
}
});
.x {
display: inline-block;
width: 10px;
height: 10px;
background-color: blue;
}
section {
background-color: yellow;
padding: 8px;
}
<main id="items">
<section id="design">
<div class="item">
<div class="x"></div>
<h1>Design stuff</h1>
</div>
</section>
<section id="art">
<div class="item">
<h1>Art stuff</h1>
<div class="x"></div>
</div>
</section>
</main>
Add the event listener to each element using a for of loop:
var openbtnList = document.getElementsByClassName("x");
for (let x of openbtnList) {
x.addEventListener("click", clickX, false);
};
function clickX() {
this.parentElement.classList.toggle("red"); // sstyle.backgroundColor = "red";
}
main {
display: flex;
}
.item {
width: 80px;
height: 100px;
padding: 30px;
}
.item::before {
content: " ";
background: url(http://placekitten.com/80/100) center/cover;
width: 80px;
height: 100px;
position: absolute;
}
.x::before {
content: "X";
color: white;
font: 30px/30px sans-serif;
padding: 10px;
position: absolute;
}
.red {
background: rgba(255, 0, 0, 0.5);
}
<main>
<div class="item">
<div class="x"></div>
</div>
<div class="item">
<div class="x"></div>
</div>
<div class="item">
<div class="x"></div>
</div>
</main>

div style change on click is not working

I have some div i want change selective div position to center means suppose I select the first two div only that div text move to center on click
$("#key").click(function myfunction() {
$("div").css("text-align", center);
});
div {
background-color: yellow;
margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="key">clickme</button>
<div onselect="myfunction()">blabla</div>
<div onselect="myfunction()">cat</div>
<div onselect="myfunction()">rose</div>
You don't need to give name to click function. It can be anonymous. Also it should be $("div").css("text-align", 'center') to assign a css property.
function myfunction() {
//Not sure why you have this on div.
}
$(document).ready(function() {
$("#key").click(function() {
$("div").css("text-align", 'center')
});
});
div {
background-color: yellow;
margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="key">clickme</button>
<div onselect="myfunction()">blabla</div>
<div onselect="myfunction()">cat</div>
<div onselect="myfunction()">rose</div>
Set(toggle) selected class on click of element
Remove inline event onselect
Set center property to only those elements which are having selected class
Set property in quotes, $("div").css("text-align", 'center');
$("#key").click(function myfunction() {
$("div.toGrab:not(.selected)").css("text-align", '');
$("div.selected").css("text-align", 'center');
});
$("div.toGrab").on("click", function() {
$(this).toggleClass('selected');
});
div {
background-color: yellow;
margin-top: 20px;
cursor: pointer;
}
.selected {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="key">clickme</button>
<div class='toGrab'>blabla</div>
<div class='toGrab'>cat</div>
<div class='toGrab'>rose</div>
Just a minor miss, need to assign value as string as shown below:
$("#key").click(function() {
$("div").css("text-align", "center");
});
If you want to give margin than also number will be specified as string as:
$("#key").click(function() {
$("div").css("padding", "50");
});
#aswathy your all code is okay, only you missed "text-align", 'center'
center property should be in single quotes
$("#key").click(function myfunction() {
$("div").css("text-align", 'center');
});
div {
background-color: yellow;
margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="key">clickme</button>
<div onselect="myfunction()">blabla</div>
<div onselect="myfunction()">cat</div>
<div onselect="myfunction()">rose</div>

Moving elements between 2 boxes

I have looked through same questions on this topic but somehow suggested solutions do not work for me :/
Problem is that divs get moved from #box1 to #box2 only once. If detach() used then divs are clickable in #box2 but get rearranged when clicked. If remove()used divs are not clickable in #box2 at all (event listener gone?). I have a feeling that the process of moving the divs is somehow not really complete and I ether have duplicates around in DOM or moved divs disappear entirely and do not react to clicks.
I tried detach(), remove() and appendTo() in various combinations and the best I can get is in the fiddle below
http://jsfiddle.net/uoz3t914/13/
$('#box1 .item' ).on('click', function() {
// $( this ).detach().appendTo('#box2'); moves divs around in #box2
$( this ).remove().appendTo('#box2');
});
$('#box2 .item' ).on('click', function() {
// $( this ).detach().appendTo('#box2'); moves divs around in #box2
$( this ).appendTo('#box1');
});
In your case you have to use the Event Delegation
$('#box1' ).off().on('click','.item', function() {
// $( this ).detach().appendTo('#box2'); moves divs around in #box2
$( this ).appendTo('#box2');
});
$('#box2' ).off().on('click', '.item', function() {
// $( this ).detach().appendTo('#box2'); moves divs around in #box2
$( this ).appendTo('#box1');
});
You attach the event to the parent, that propagate it to the children, and then any time that you attach the event, put an off() to detach it.
$('#box1' ).off().on('click','.item', function() {
// $( this ).detach().appendTo('#box2'); moves divs around in #box2
$( this ).appendTo('#box2');
});
$('#box2' ).off().on('click', '.item', function() {
// $( this ).detach().appendTo('#box2'); moves divs around in #box2
$( this ).appendTo('#box1');
});
.item {
width: 50px;
height: 50px;
float: left;
}
#box1 {
border: 1px dotted blue;
position: relative;
width: 200px;
height: 100px;
}
#i1 {
background-color: yellow;
}
#i2 {
background-color: green;
}
#i3 {
background-color: red;
}
#box2{
border: 1px solid black;
width: 250px;
height: 100px;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id ="box1">
<div class ="item" id ="i1"></div>
<div class ="item" id ="i2"></div>
<div class ="item" id ="i3"></div>
</div>
<div id = "box2">
</div>
You can move them between the boxes with:
$('#box1, #box2').on('click', '.item', function () {
$(this).appendTo($(this).parent().prop('id') == 'box1' ? '#box2' : '#box1');
});
$('#box1, #box2').on('click', '.item', function () {
$(this).appendTo($(this).parent().prop('id') == 'box1' ? '#box2' : '#box1');
});
.item {
width: 50px;
height: 50px;
float: left;
}
#box1 {
border: 1px dotted blue;
position: relative;
width: 200px;
height: 100px;
}
#i1 {
background-color: yellow;
}
#i2 {
background-color: green;
}
#i3 {
background-color: red;
}
#box2 {
border: 1px solid black;
width: 250px;
height: 100px;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="box1">
<div class="item" id="i1"></div>
<div class="item" id="i2"></div>
<div class="item" id="i3"></div>
</div>
<div id="box2"></div>
This uses .on()'s event delegation syntax to handle the elements, and a ternary operator to determine which box the element exists in.
Use this html:
<div id="wrapper">
<div id ="box1" class="container">
<div class ="item" id ="i1"></div>
<div class ="item" id ="i2"></div>
<div class ="item" id ="i3"></div>
</div>
<div id = "box2" class="container">
</div>
</div>
and this javascript
$('.item').on('click', function(){
var index = $("#wrapper > .container").index($(this).parent()),
maxIndex = $('#wrapper > .container').length,
nextIndex = (index + 1) < maxIndex ? (index + 1) : 0;
$(this).appendTo($('#wrapper > .container').eq(nextIndex));
});
in your fiddle to move boxes between any number of containers
You may also add Box3, Box4 (with class .container) etc. into the "#wrapper div", you may do it dynamycally

Categories

Resources