Droppable doesn't fire after changing divs - javascript

I'm trying to simulate an animate effect via jQuery that consists drag and drop as events to be fired. The code I use seems to be fine until the point when I have to swap divs by setting their display to none/block. Whenever I swap to the first div it perfectly executes the animation but when it gets on the 2nd div (after swapped) it doesn't fire the droppable event. I chose to have id selectors for the respective divs to instance the container of the droppable event hence to animate. I'm stuck and are out of any solution after searching numerous results so far. Thank you in advance. Here is my JS fiddle I prepared to easily understand my problem.
<html>
<head>
<style>
#wrapper {
border: 1px solid gray;
height:300px;
margin: 0 auto;
padding: 20px 20px 20px 20px;
position:relative;
text-align:center;
width:600px;
}
p {
display:inline;
font-family:Calibri;
font-size:20px;
color: #0b1207;
text-shadow: #63c9b8 0px 10px 10px;
}
#div1, #div2 {
border: 1px dotted green;
bottom:0;
margin-left:100px;
position: absolute;
}
#div1 {
background-color: orange;
height:200px;
width:300px;
}
#div2 {
background-color: green;
display:none;
height:100px;
width:300px;
}
#btnchange {
background-color:black;
border-radius:10px;
color: #fff;
height:35px;
margin-top:10px;
margin-left:100px;
position:absolute;
width:80px;
}
.example {
border: 1px solid red;
background-color: blue;
height:75px;
margin: 5px auto 0 ;
width:75px;
}
</style>
</head>
<body>
<div id='wrapper'>
<p></p>
<div id='div1'></div>
<div id='div2'></div>
</div>
<button id ='btnchange' type='button'>Change</button>
<div class='example'></div>
<script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<script src="http://biostall.com/wp-content/uploads/2010/07/jquery-swapsies.js"></script>
<script type="text/javascript">
var id = 1;
var parent = document.getElementById('wrapper');
var makina = parent.children[id].id;
$(function(){
$( "#draggable" ).draggable({
connectToSortable: "#sortable",
helper: "clone",
revert: "invalid"
});
$('.example').draggable({
containtment: "#" + makina,
cursor: "pointer",
revert: true
});
$('#btnchange').click(function(){
if (id == 1)
{
document.getElementById(makina).style.display = 'none';
id = 2;
makina = parent.children[id].id;
document.getElementById(makina).style.display = 'block';
document.getElementById('wrapper').children[0].innerText = makina;
}
else
{
document.getElementById(makina).style.display = 'none';
id = 1;
makina = parent.children[id].id;
document.getElementById(makina).style.display = 'block';
document.getElementById('wrapper').children[0].innerText = makina;
}
console.log(makina);
});
$("#" + makina).droppable({
drop: function(){
doAnimate(makina);}
});
});
function doAnimate(container)
{
$('#'+ container).animate({height: '+=10px'}, 500, function(){
var message = container.clientHeight;
$(this).html(message);
});
}
</script>
</body>
</html>
http://jsfiddle.net/xoxxbr4t/6/

Your problem is you were only calling droppable once, on only one of the items. Once the .droppable() function is also put inside the change button click, it should work.
put this inside change function:
$("#" + makina).droppable({
drop: function () {
doAnimate(makina);
}
});
example:
http://jsfiddle.net/xoxxbr4t/7/

You aren't binding droppable to your second element. You call this function once:
$("#" + makina).droppable({
drop: function () {
doAnimate(makina);
}
});
Since your "makina" at this point is div1, that's the only thing that gets bound. I made that it's own function:
function setDroppable(makina) {
$("#" + makina).droppable({
drop: function () {
doAnimate(makina);
}
});
}
And then called it for both divs in your setup:
setDroppable('div1');
setDroppable('div2');
And now it works fine. Here's the updated fiddle

Thanks Michal indeed that was the answer but I think a good programmer would reduce the redundant snippet of code as far as I can tell those are duplicate lines from the $(document).ready() function. However it's a solution. And right after I read your post I decided to post the answer myself as it follows:
//Previous
$("#" + makina).droppable({
drop: function () {
doAnimate(makina);
}
});
//Current
$("#wrapper").droppable({
drop: function () {
doAnimate(makina);
}
});
Since I'm using nested divs I then realised that I could make the parent div droppable and just animate the child which is active(shown).

Related

How can I make an element on hover?

All I'm trying to do is something like this mechanism:
Here is what I've tried so far:
$(document).ready(function(){
$('a').bind('mouseenter', function() {
var self = $(this);
this.iid = setInterval(function() {
var tag_name = self.text(),
top = self.position().top + self.outerHeight(true),
left = self.position().left;
self.append("<div class='tag_info'>Some explanations about"+tag_name+"</div>")
$(".tag_info").css({top: top + "px", left: left + "px"}).fadeIn(200);
}, 525);
}).bind('mouseleave', function(){
this.iid && clearInterval(this.iid);
});
});
body{
padding: 20px;
}
a {
color: #3e6d8e !important;
background-color: #E1ECF4;
padding: 2px 5px;
}
.tag_info{
position: reletive;
width: 130px;
height: 30px;
display:none;
background-color: black;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a>tag1</a>
<a>tag2</a>
As you see, it will be repeated every time. How can I execute it once per hover? And why the position doesn't apply?
Also is what I'm doing a right algorithm for such thing?
Thank you.
I am not sure why you are using setInterval but I think this should work. I removed setInterval and everytime the mouseenter event occurs we can append <div class='tag_info'> and every time mouseleave event occurs we can remove the the appended div.
$(document).ready(function(){
$('#test').bind('mouseenter', function() {
var self = $(this);
var tag_name = self.text(),
top = self.position().top + self.outerHeight(true),
left = self.position().left;
self.append("<div class='tag_info'>Some explanations about"+tag_name+"</div>")
$(".tag_info").css({top: top + "px", left: left + "px"}).fadeIn(200);
}).bind('mouseleave', function(){
$(this).children('.tag_info').remove();
});
});
body{
padding: 20px;
}
a {
color: #3e6d8e !important;
background-color: #E1ECF4;
padding: 2px 5px;
}
.tag_info{
position: reletive;
width: 130px;
height: 30px;
display:none;
background-color: black;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="test">tag1</a>
Like Dij said:
What you're doing:
setInterval - (repeats your function every 525ms)
What you want:
setTimeout - (executes your function once after 525ms delay)
Read more:
setInterval https://www.w3schools.com/jsref/met_win_setinterval.asp
setTimeout https://www.w3schools.com/jsref/met_win_settimeout.asp

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>

draggable sets left to zero

The goal of the script is drag element but leave copy of the element.
function makeDraggable() {
$('.col-md-4').addClass('is-draggable');
$('.is-draggable').draggable({
start: function(event, ui){
if($(this).hasClass('not-draggable'))
return;
var cl = $(this).clone();
$(this).after(cl);
var of = cl.offset();
$(this).addClass('rect').offset({top:of.top,left:of.left}).css({width:cl.css('width'), height:cl.css('height')});
makeDraggable();
$(this).addClass('not-draggable');
}
});
}
makeDraggable();
When you mousedown on some boxes it clones box and then draggable placing this element to the left top corner and don't allow to set my own offset. I want the dragable element left on the same place and don't jump. Demo jsfidle
You can't use offset because it's already used by the drag event. You can use margins to offset your draggable.
Also, use ui.helper to get the offset
var of = $(ui.helper).offset();
$(this).addClass('rect').css({'margin-top':of.top,'margin-left':of.left}).css({width:cl.css('width'), height:cl.css('height')});
Demo
External JSFiddle: http://jsfiddle.net/9QmbG/22
function makeDraggable() {
$('.col-md-4').addClass('is-draggable');
$('.is-draggable').draggable({
start: function (event, ui) {
var $this = $(this);
if ($this.hasClass('not-draggable')) return;
var cl = $this.clone();
$this.after(cl);
var of = $(ui.helper).offset();
$this.addClass('rect').css({
'margin-top': of.top,
'margin-left': of.left
}).css({
width: cl.css('width'),
height: cl.css('height')
});
makeDraggable();
$this.addClass('not-draggable');
}
});
}
makeDraggable();
#score {
height:50px;
}
.col-md-4 {
width:40px;
height:40px;
margin:10px 20px;
border:1px solid #000000;
float:left;
cursor:pointer;
text-align:center;
line-height:40px;
position:relative;
top:0;
left:0;
}
.rect {
position: absolute;
z-index:100000;
border-style: dashed;
border-width: 2px;
}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.js"></script>
<div id="score"> </div>
<div class="col-md-4">1</div>
<div class="col-md-4">2</div>
<div class="col-md-4">3</div>

Display hidden container element - hover only works after I click the container

I have a situation like this set up:
http://jsfiddle.net/gz4Z7/2/
The difference in my situation is that all of the elements are created in javascript with document.createElement, and they are appended to the DOM of various webpages on the internet.
Everything works great except one thing: The hover functionality doesn't work until I click on the container. This only happens on some webpages.
My question is: What would cause the need to click on the container element in order for the hover functionality of its children to work? I have tried doing a focus() on the container element but it doesn't seem to make a difference.
Here is the fiddle code:
<input id="myInput" type="text"/>
<myContainer id="myContainer">
<outerThing id="outerThing">
<myThing id="myThing"></myThing>
</outerThing>
</myContainer>
<button type="button" onclick="buttonClick()">show container</button>
#myContainer {
position: absolute;
top:100px;
bottom:auto;
right:auto;
left:100px;
width:200px;
height:200px;
display: none;
background-color: red;
}
#outerThing{
width:50px;
height:50px;
margin-top: 10px;
margin-left: 10px;
display: block;
background-color: white;
}
#myThing{
width:20px;
height:20px;
margin-top: 15px;
margin-left: 15px;
display: none;
background-color: blue;
}
function buttonClick() {
document.getElementById("myInput").focus();
var cont = document.getElementById("myContainer");
cont.style.display = "block";
var outerThing = document.getElementById("outerThing");
$( outerThing ).hover(
function()
{
$(this).children(":last").css( "display", "inline-block" );
},
function()
{
$(this).children(":last").css( "display", "none" );
});
}
$(document).ready(function({
function buttonClick() {
document.getElementById("myInput").focus();
var cont = document.getElementById("myContainer");
cont.style.display = "block";
var outerThing = document.getElementById("outerThing");
$( outerThing ).hover(
function()
{
$(this).children(":last").css( "display", "inline-block" );
},
function()
{
$(this).children(":last").css( "display", "none" );
});
}
});
Like this

Creating a grid overlay over image

I made a script (using mootools library) that is supposed to overlay an image with a table grid and when each grid cell is clicked/dragged over its background color changes 'highlighting' the cell.
Current code creates a table and positions it over the element (el, image in this case). Table was used since I am planning to add rectangle select tool later on, and it seemed easiest way to do it.
<html>
<head>
<title></title>
<script type="text/javascript" src="mootools.js"></script>
<script type="text/javascript">
var SetGrid = function(el, sz, nr, nc){
//get number of rows/columns according to the 'grid' size
numcols = el.getSize().x/sz;
numrows = el.getSize().y/sz;
//create table element for injecting cols/rows
var gridTable = new Element('table', {
'id' : 'gridTable',
'styles' : {
'width' : el.getSize().x,
'height' : el.getSize().y,
'top' : el.getCoordinates().top,
'left' : el.getCoordinates().left
}
});
//inject rows/cols into gridTable
for (row = 1; row<=numrows; row++){
thisRow = new Element('tr', {
'id' : row,
'class' : 'gridRow'
});
for(col = 1; col<=numcols; col++){
thisCol = new Element('td', {
'id' : col,
'class' : 'gridCol0'
});
//each cell gets down/up over event... down starts dragging|up stops|over draws area if down was fired
thisCol.addEvents({
'mousedown' : function(){
dragFlag = true;
startRow = this.getParent().get('id');
startCol = this.get('id');
},
'mouseup' : function(){
dragFlag = false;
},
'mouseover' : function(){
if (dragFlag==true){
this.set('class', 'gridCol'+$$('#lvlSelect .on').get('value'));
}
},
'click' : function(){
//this.set('class', 'gridCol'+$$('#lvlSelect .on').get('id').substr(3, 1) );
str = $$('#lvlSelect .on').get('id');
alert(str.substr(2, 3));
}
});
thisCol.inject(thisRow, 'bottom');
};
thisRow.inject(gridTable, 'bottom');
};
gridTable.inject(el.getParent());
}
//sens level selector func
var SetSensitivitySelector = function(el, sz, nr, nc){
$$('#lvlSelect ul li').each(function(el){
el.addEvents({
'click' : function(){
$$('#lvlSelect ul li').set('class', '');
this.set('class', 'on');
},
'mouseover' : function(){
el.setStyle('cursor','pointer');
},
'mouseout' : function(){
el.setStyle('cursor','');
}
});
});
}
//execute
window.addEvent('load', function(){
SetGrid($('imagetomap'), 32);
SetSensitivitySelector();
});
</script>
<style>
#imagetomapdiv { float:left; display: block; }
#gridTable { border:1px solid red; border-collapse:collapse; position:absolute; z-index:5; }
#gridTable td { opacity:0.2; filter:alpha(opacity=20); }
#gridTable .gridCol0 { border:1px solid gray; background-color: none; }
#gridTable .gridCol1 { border:1px solid gray; background-color: green; }
#gridTable .gridCol2 { border:1px solid gray; background-color: blue; }
#gridTable .gridCol3 { border:1px solid gray; background-color: yellow; }
#gridTable .gridCol4 { border:1px solid gray; background-color: orange; }
#gridTable .gridCol5 { border:1px solid gray; background-color: red; }
#lvlSelect ul {float: left; display:block; position:relative; margin-left: 20px; padding: 10px; }
#lvlSelect ul li { width:40px; text-align:center; display:block; border:1px solid black; position:relative; padding: 10px; list-style:none; opacity:0.2; filter:alpha(opacity=20); }
#lvlSelect ul li.on { opacity:1; filter:alpha(opacity=100); }
#lvlSelect ul #li0 { background-color: none; }
#lvlSelect ul #li1 { background-color: green; }
#lvlSelect ul #li2 { background-color: blue; }
#lvlSelect ul #li3 { background-color: yellow; }
#lvlSelect ul #li4 { background-color: orange; }
#lvlSelect ul #li5 { background-color: red; }
</style>
</head>
<body>
<div id="imagetomapdiv">
<img id="imagetomap" src="1.png">
</div>
<div id="lvlSelect">
<ul>
<li value="0" id="li0">0</li>
<li value="1" id="li1">1</li>
<li value="2" id="li2">2</li>
<li value="3" id="li3">3</li>
<li value="4" id="li4">4</li>
<li value="5" id="li5" class="on">5</li>
</ul>
</div>
</body>
</html>
There are two problems: while it works just fine in FF, IE and Chrome do not create the table if the page is refreshed. If you go back to directory root and click on the link to the file the grid table is displayed, if you hit 'refresh' button -- the script runs but the table is not injected.
Secondly, although the table HTML is injected in IE, it does not display it. I tried adding nbsp's to make sure its not ignored -- to no avail.
Any suggestions on improving code or help with the issues is appreciated.
Thanks!
Try adding a docType dec at the top of the page IE:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

Categories

Resources