Moving elements between 2 boxes - javascript

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

Related

Jquery: How to hide an element while it is in orther element?

how to hide a "cube-2" by click on "click-me" that its included by "cube-2"?
I made an event but it deleted all of my cube-2, I want to hide cube-2 one by one. Anyone can solve this? please help me.
$('.cube-1').click(function name(params) {
$('.cube-1').append('<div class="cube-2"><div class="click-me">click me to hide this cube</div></div>');
// how to add event click on "click-me" to hide "cube-2"??
})
.cube-1 {
width: 100px;
height: 100px;
float: left;
background: blue;
}
.cube-2 {
margin-left: 100px;
width: 100px;
height: 100px;
float: left;
background: red;
}
.click-me {
width: 100%;
height: 50px;
background: white;
}
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
</head>
<div class="cube-1"></div>
</html>
You can add an id to your cube-2 div and it's corresponding click-me anchor tag and remove only the div with that Id.
You may also want to check Template string
$('.cube-1').click(function name(e) {
var cubeCounter = 1;
if (e.target.className == "cube-1") {
$('.cube-1').append(`<div class=cube-2 id=cube-${cubeCounter}><div class=click-me id=${cubeCounter}>click me to hide this cube</div></div>`);
cubeCounter++;
}
})
$(document).on('click', '.click-me', function name(e) {
var cubeId = e.target.id;
$(`#cube-${cubeId}`).remove();
})
you need to handle dyanamic click event of second cube and prevent click event of parent control, when child cube is clicked
$('.cube-1').click(function name(e) {
if(e.target.className == "cube-1")
{
$('.cube-1').append('<div class="cube-2"><div class="click-me">click me to
hide this cube</div></div>');
}
});
$(document).on('click','.cube-2',function name(e)
{
$(this).remove();
// how to add event click on "click-me" to hide "cube-2"??
})
Please check working demo [Link]
https://jsfiddle.net/2L3k5hcb/
You just need to bind your click on div while you appending your cube-2.
Add your script as below-
$('.cube-1').on('click',function(event){
$('.cube-1').append('click me to hide this cube');
})
function myFunction(param) {
event.stopPropagation();
$(param).remove();
}
you can use below method for dynamicly generated elements.
$(document).on('click', '.click-me', function (e) {
$(this).hide();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Try this
$(document.body).on('click', '.cube-2', function (event) {
$(this).hide();
});
$('.cube-1').click(function(event) {
if(event.target.className =='cube-1')
$('.cube-1').append('<div class="cube-2"><div class="click-me">click me to hide this cube</div></div>');
// how to add event click on "click-me" to hide "cube-2"??
})
.cube-1 {
width: 100px;
height: 100px;
float: left;
background: blue;
}
.cube-2 {
margin-left: 100px;
width: 100px;
height: 100px;
float: left;
background: red;
}
.click-me {
width: 100%;
height: 50px;
background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cube-1"></div>

How removing dragged element only if it has a certain class?

I want to remove a dragged element, but it should only be removed when it doesn't have the class "nodrop".
here's my current code it removes all elements wheter i included an if function:
$(".löschen").droppable({
drop: function(event, ui) {
if (!$(this).hasClass("nodrop")){
ui.draggable.remove();
findTotal();
}
}});
I don't have any plan what I've done wrong...
You get the current drop container (.löschen) with $(this). With $(ui.draggable) you get the dropped element with class nodrop.
$(".draggable").draggable();
$(".löschen").droppable({
drop: function(event, ui) {
var $dropContainer = $(this);
var $dragContainer = $(ui.draggable)
console.log($dropContainer, $dragContainer);
if (!$dragContainer.hasClass("nodrop")){
$dragContainer.remove();
}
}});
.draggable {
width: 100px;
height: 100px;
}
.drop {
background-color: green;
}
.nodrop {
background-color: red;
}
.löschen {
width: 200px;
height: 200px;
background-color: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="draggable nodrop">NO DROP</div>
<div class="draggable drop">DROP</div>
<div class="löschen">TRASH</div>

change size of div function doesn't work

I have a function that alters the size of a div when I click on it. Now I have to write the onclick command in my html page, but I want it to stand in the extern .js file.
Now in html:
<div id="box1" class="kaesten" onclick="changeSize('box1')"> Title 1 </div>
What I want:
<div id="box1" class="kaesten" > Title 1 </div>
Tried something in jquery but it didn't work:
function changeSize(id) {
var elem = document.getElementById(id);
var currentAbsoluteElem = document.getElementById('dummy');
var text = elem.innerHTML;
currentAbsoluteElem.innerHTML = text;
currentAbsoluteElem.setAttribute('style', 'display:block');
/*Extra styling neeed to be done here*/
}
var elems = document.getElementsByClassName('kaesten');
for (var i = 0; i < elems.length; i++) {
elems[i].onclick = function() {
changeSize(this.id);
}
}
var absoluteCl = document.getElementsByClassName('absoluteclass');
absoluteCl[0].onclick = function() {
console.log(document.getElementsByClassName('absoluteclass'))
document.getElementsByClassName('absoluteclass')[0].setAttribute('style', 'display:none');
}
$(document).ready(function() {
$('.kaesten').click(function() {
changeSize($(this).attr('id'));
});
});
.kaesten {
width: 240px;
height: 300px;
background-color: darkgrey;
background-position: center;
background-repeat: no-repeat;
text-shadow: 0px 0px 3px #000;
border: 5px solid #F0F8ff;
vertical-align: top;
text-shadow: 3px 3px 4px #777;
float: left;
margin-left: 30px;
}
.absoluteclass {
position: absolute;
background-color: darkgrey;
width: 600px;
height: 600px;
left: calc(30%);
display: none;
}
<div id="box1" class="kaesten">title1</div>
<div id="box2" class="kaesten">title2</div>
<div id="box3" class="kaesten">title3</div>
<div id="box4" class="kaesten">title4</div>
<div id="dummy" class="absoluteclass"></div>
I know it works in the fiddle, but I don't know why it doesn't work on my homepage without writing the function in the div's.
I guess the problem is that you are trying to assign the onclick event handler before the DOM is actually rendered and ready. My suggestion is to wrap your "initialization code" inside a $(document).ready() method. As follows:
$(document).ready(function() {
// Apply the on click event handlers here, using jQuery or not
// For instance:
$('.kaesten').click(function() {
changeSize($(this).attr('id'));
});
});
if you want to pass the id from jquery to your function you should do it like this:
$(function(){
$(".kaesten").click(function(){
changeSize($(this).attr("id"));
});
});
you can use .css in jquery
$(function(){
$(".kaesten").click(function(){
$(this).css({'width' : '600px' , 'height' : '600px'});;
});
});

jQuery | detach(), append() scope

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.

jquery-ui : drop&drag inventory with stackable items

Hello everyone,
I'm building a drop&drag inventory panel for my webgame, but I was unable to make it work with stackable elements. I have simplified the whole inventory so that it's less confusing.
FIrst off, let me explain how do I expect it to work:
Every .item element can be dropped on any free .inv_slot.
If I try to drop an .item element on another .item that does not contain class .stackable, it will simply activate the draggable's revert() function.
if I try to drop the .item element on an .item that does have the .stackable class,
it will only remove the clone/helper. (Later on I will addd an function that only increases the items stack size.)
Now what's wrong with the below example :
in case an .item accidentally dropped on border or between two .inv_slotslots, the Revert animation is not activated. It does work however, while dropping the .item element outside the #panel.
Also if I accidentally dropped an .item between two .inv_slot elements, it will behave as if the .item was dropped on a .stackable item. So it will remove the clone instead of reverting back to it's prev. position. (Most likely an issue with the selector in drop: method)
If I drop a .stackable item over another .stackable item, it does not refresh the cursor. It seems to be stuck in the drag mode which activates the "pointer" cursor.
Now here's the (partialy working) example:
$(document).ready(function() {
//var prev_el = '';
var item_isStackable = "";
$( ".item").draggable({
scroll: true,
revert: function(isValidEl)
{
if(isValidEl)
{
return false;
}else{
return true;
}
},
helper: "clone",
cursor: "pointer",
stack: false,
zIndex: 27,
drag: function(event, ui)
{
item_isStackable = $(this).hasClass("stackable");
},
});
$( ".inv_slot" ).droppable({
accept: ".item",
drop: function( event, ui ) {
var item = $(this).find(".item");
if(item.length == 0) /// See if there any items already in the currently selected inventory slot //
{
console.log("Inserting");
ui.draggable.detach().appendTo($(this)); // if none, insert the item into athe free slot ///
}
else if(item_isStackable == true && item.hasClass("stackable")){
console.log("Increasing ");
ui.draggable.detach(); /// If yes, just destroy the clone ///
}else{
console.log("reverting back");
// in case it's not .inv_slot , revert the item back to it's previous position //
ui.draggable.animate(ui.draggable.data().origPosition,"slow");
}
}
});
});
#panel
{
width: 340px;
height: 44px;
border: 1px solid #000;
padding: 4px;
}
.inv_slot
{
z-index: 22;
position: relative;
width: 40px;
height: 40px;
border: 1px solid red;
float: left;
}
.inv_slot .slot_pos{
z-index: 24;
position: absolute;
margin-left: 50%;
left: -4px; top: 2px;
}
.item
{
position: relative;
z-index: 25;
margin: 4px;
width: 30px;
height: 30px;
border: 1px solid blue;
}
.item.stackable
{
border: 1px solid green;
}
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.js"></script>
<div id="panel">
<div class="inv_slot">
<div class="item stackable" ></div>
<span class="slot_pos">0</span>
</div>
<div class="inv_slot">
<div class="item"> </div>
<span class="slot_pos">1</span>
</div>
<div class="inv_slot">
<div class="item stackable"> </div>
<span class="slot_pos">2</span>
</div>
<div class="inv_slot"><span class="slot_pos">3</span> </div>
<div class="inv_slot"><span class="slot_pos">4</span> </div>
<div class="inv_slot"><span class="slot_pos">5</span> </div>
<div class="inv_slot"><span class="slot_pos">6</span> </div>
<div class="inv_slot"><span class="slot_pos">7</span> </div>
</div>
I have spent couple of hours without any progress , so I'd really appreciate if someone could help me out with this one.
Thanks in advance,
Alex.
What's happening is that when you drag a box onto a border next to it, it deletes itself because it tries to stack itself. You need to change the second part of your if statement:
else if(item_isStackable == true && item.hasClass("stackable") && ui.draggable.filter(function() { var d = this; return item.filter(function() { return d == this; }).length > 0; }).length === 0)
To fix the cursor pointer problem:
.item
{
position: relative;
z-index: 25;
margin: 4px;
width: 30px;
height: 30px;
border: 1px solid blue;
cursor: default !important; /* Add this property. */
}
Fiddle.

Categories

Resources