jquery ui droppable's greedy setting is not working? - javascript

By setting droppable widget's greedy to true, only the top-most element should respond to a drop event. There's really no complexity here but I just cannot get it to work. And this is all I have so not much to work on:
CSS:
.page{
position: absolute;
width: 150px;
height: 150px;
left: 0px;
top: 0px;
text-align: center;
background: #F0FFFF;
border: 1px solid #89B;
}
HTML:
<div class = 'page' id = 'page1'> page1 </div>
<div class = 'page' id = 'page2'> page2 </div>
<div class = 'page' id = 'page3'> page3 </div>
JS:
document.ready = function(){
$('.page').draggable()
$('.page').droppable({
greedy: true,
drop: function( event, ui ){
console.log( 'assert drop once')
}
})
}
what's happening right now is that all the dropped on elements are responding to the drop event. Since there's so little code to hold on to, I have no idea how to diagnose this.

Reading the documentation for the greedy property I'm not sure I understand the same as you:
By default, when an element is dropped on nested droppables, each droppable will receive the element. However, by setting this option to true, any parent droppables will not receive the element.
For me it means if you have a large div droppable which contains another smaller div droppable then if you drop an element in the small one only the small one will receive the event.
Check this demo to understand what I'm explaining : http://jquery-ui.googlecode.com/svn/tags/1.6rc4/demos/droppable/greedy.html

Related

Events on elements created by jquery

I'm still learning jquery and I'm facing an issue that probably a lot of people have been facing which is just logic but I can't seem to find a good way to learn how to do that.
So my issue is the following:
I'm creating elements called .lieu on the page using jquery. Basically, when you enter a text and click "OK" you created another .lieu that is supposed to display the text "en passant par le bois des lutins" in the destinations tab.
The first one that is created with html is working but not the other ones.
It seems the script is able to execute on the elements created using html (that's probably due to:)
$( document ).ready(function() {});
How can I make that work using the good method?
Thanks a lot.
$(".validate").click( function(){
var name = $(this).closest(".envies").find("input[name='name']").val();
var lieu = $("<div />", {
"class": "lieu"
})
.css({
left: 0,
top: 0
})
.append($("<p>"+name+"</p>"))
.appendTo(document.body);});
$(".lieu").on("mouseenter", function(checklieu) {
var ordredestinations = $("<div />", {
"class": "lieuliste"
})
.css({
})
.append($("<p>en passant par le bois des lutins</p>"))
.appendTo(".destinations");
});
.destinations {
background-color: lightgrey;
position: fixed;
right: 0;
top: 0;
}
.envies {
background-color: grey;
position: fixed;
right: 300px;
top: 0;
width: 250px;
height: 50px;
}
.lieu{
position: absolute;
left:0px;
top: 100px;
background-color: red;
width: 200px;
height: 100px;
border-radius: 250px;
text-align: center;
vertical-align: middle;
line-height: 100px; /* The same as your div height */
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div class="lieu"><p>bois des lutins</p></div>
<div class="destinations"></div>
<div class="envies">
<input type="text" id="name" name="name" size="10" placeholder="name">
<button class="validate">OK</button>
</div>
</body>
<script type="text/javascript"></script>
A think I see your problem.
When a document (webpage) loads, specific targeted jQuery functions like yours..
$(".validate").click( function() {
// ...
});
// and...
$(".lieu").on("mouseenter", function() {
// ...
});
..will only bind upon the document being ready, more than like because you are using these inside $(document).ready(function(). So when doc is ready, the above 2 functions run and bind.
Running functions like you are within doc ready is good practice.
However, if you intend to automatically bind existing executed functions to newly added document elements.. then your first 2 functions are out of scope.
You need to look into .on() https://api.jquery.com/on/
For example, if you want newly added document elements like .lieu divs, to be hit by your mouseover function, then you use .on function like this...
$(document).on("mouseenter", ".lieu", function()
The .on() second param is the .lieu selector, within $(document) as the main jQuery selector object.
Meaning if you append any number of new .lieu divs to the document html, using .on() selector param within $(document) will always be in scope of the mouseover event on this selector.

jQuery drag and drop with revert

Using jQuery UI, I've just set up a simple test with draggable and droppable
HTML:
<div>
<img src="img/2.jpg" alt="Donut" id="a" class="drag"><span id="4" class="drop" >Eclair</span>
</div>
<div>
<img src="img/3.jpg" alt="Eclair" id="b" class="drag"><span id="3" class="drop">Donut</span>
</div>
I am trying to drag the first image and drop into the related span.Along with this if i drag and drop first image at id="4" it should revert back to its original position.Similarly when i drag and drop second image at id="3" it should revert back to its original position.
script:
$(function () {
$("#a").draggable({
revert: "valid",
});
$("#b").draggable({
revert: "invalid",
});
$(".drop").droppable({
accept: '.drop',
});
});
I can drag the image but could not drop it in a correct position.What i am doing wrong?
css:
.drag,.drop{
width:130px !important;
height: 130px !important;
border:2px solid !important;
margin-top:10px !important;
margin-left: 15% !important;
}
.drop{
float: right !important;
margin-right: 30% !important;
}
https://jsfiddle.net/jjewhwLt/
You need to style the elements a bit different, add the draggable() to the .drag class and you can then append the droppable() to the .drag elements. I've also added data-id to both drag and drop elements to be able to match them. I hope this is what you're looking for:
Updated FIDDLE.
$(".drag").draggable({
revert: 'invalid'
});
$(".drop").droppable({
accept: function(drag) {
var drop_id = $(this).attr('data-id');
var drag_id = $(drag).attr('data-id');
return drop_id === drag_id;
}
});
I had a bit of trouble understanding the question here, but i'll give it my best shot at explaining what I think you're trying to achieve.
I'd recommend in the future to start naming out what you're trying to do clearly so that you yourself can understand it while you're working. Stuff like "A" and "B", "3" and "4" etc. will get confusing very very fast with what you're working on.
What I took from this was that you are trying to get each container to accept it's corresponding image. Here's a cleaned up version of your jsfiddle: https://jsfiddle.net/8hr3vf3L/
I've separated out the images + drop areas in the HTML first and replaced the images that were broken with placeholders:
<div class="images">
<img src="http://placehold.it/120?text=donut" alt="Donut" id="donut" class="drag">
<img src="http://placehold.it/120?text=eclair" alt="Eclair" id="eclair" class="drag">
</div>
<div class="drop-areas">
<div class="drop-area" id="eclairArea">Eclair</div>
<div class="drop-area" id="donutArea">Donut</div>
</div>
Then cleaned up the CSS a little to make it a bit more generic:
.drop-areas {
margin-top: 40px;
}
.drop-area,
.drag {
display: inline-block;
width: 120px;
height: 120px;
border: 2px solid black;
margin-right: 20px;
}
.drag { border: none; }
Then finally your JS, which I hope makes more sense for you now. revert within a draggable function when named invalid will send the square back to where it was if it isn't in an area where it's accepted, which is explained by the droppable functions, which in this case I've separated out to make a little more sense to you, but you could I assume, make this programmatically check which image is being dropped in. As you can see, #eclairArea is set up to only accept the #eclair and vice-versa.
$(function () {
$(".drag").draggable({
revert: "invalid",
});
$("#eclairArea").droppable({
accept: '#eclair'
});
$("#donutArea").droppable({
accept: '#donut'
});
});

Click Propagation failing in Jquery

For part of the site I'm working on, I have a set of sidebars that can pull out. To have them hide when the users are done with them, I've set up a div with a click event (see below) so that whenever the user clicks somewhere outside of the sidebar, the sidebar closes. The problem that I'm running into, however, is that the click event handler is grabbing the event, running its method, and then the click event seems to stop. I've tried using return true and a few other things I've found around here and the internet, but the click event just seems to die.
$('.clickaway').click(function() {
$('body').removeClass(drawerClasses.join(' '));
return true;
});
EDIT: Here is a fiddle with an example: https://jsfiddle.net/2g7zehtn/1/
The goal is to have the drawer out and still be able to click the button to change the color of the text.
The issue is your .clickaway layer is sitting above everything that's interactive, such as your button. So clicking the button, you're actually clicking the layer.
One thing you could do is apply a higher stacking order for elements you want to interact with, above the .clickaway layer. For example, if we apply position: relative, like this:
.show-drawerHotkey .ColorButton {
position: relative;
}
The element will now be in a higher stacking order (since it comes after the clickaway, and we've applied no z-index to clickaway)
Here's a fiddle that demonstrates: https://jsfiddle.net/2g7zehtn/5/
Using this somewhat famous SO answer as a guide, you can bind to the $(document).mouseup(); event and determine whether certain "toggling" conditions apply:
[EDIT] - Example updated to illustrate clicking a link outside of the containing div.
// Resource: https://stackoverflow.com/questions/1403615/use-jquery-to-hide-a-div-when-the-user-clicks-outside-of-it
var m = $('#menu');
var c = $('#menuContainer');
var i = $('#menuIcon');
i.click(function() {
m.toggle("slow");
});
$(document).mouseup(function(e) {
console.log(e.target); // <-- see what the target is...
if (!c.is(e.target) && c.has(e.target).length === 0) {
m.hide("slow");
}
});
#menuIcon {
height: 15px;
width: 15px;
background-color: steelblue;
cursor: pointer;
}
#menuContainer {
height: 600px;
width: 250px;
}
#menu {
display: none;
height: 600px;
width: 250px;
border: dashed 2px teal;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I'm a link outside of the container
<div id="menuContainer">
<div id="menuIcon"></div>
<div id="menu"></div>
</div>

Make HTML element inherit events from custom object

In the webpage I'm working I have a lot of small images to wich I want to assign the same set of events. Instead of adding them one by one, I thought it would be more elegant if I could make that type of element inherit these events.
What comes to my mind is something like :
function InheritEvents(){};
InheritEvents.prototype.onmouseover = function(){...action a..};
InheritEvents.prototype.onmouseout = function(){...action b..};
var temp = originalHTMLElement.constructor; //(in this case img)
originalHTMLElement.prototype = new InheritEvents();
originalHTMLElement.constructor = temp;
a) Am I not disturbing the originalHTMLElement ?
b) Is it possible to name the custom object property, for example
".onmouseover" like in the classic way:
originalHTMLElement.onmouseover = function()... ?
c) More conceptual: Is it possible to mix your custom objects with HTML
elemenst / DOM nodes ?
I would strongly recommend against this. It probably wouldn't work anyway, but messing with the prototypes of host objects is, in general, a bad idea.
I don't think there should really be a problem with iterating through the target elements and attaching events to them, but if you don't like that, you can use event delegation:
window.onload = function() {
document.getElementById("images").onclick = function(e) {
if (e.target && e.target.classList.contains("clickable")) {
e.stopPropagation();
console.log("I've been clicked!");
}
}
}
#images div {
width: 40px;
height: 40px;
float: left;
margin: 5px;
background-color: blue;
}
#images div.clickable {
background-color: red;
}
#images + * {
clear: both;
}
<div>
<div id="images">
<!-- Pretend that these DIVs are your images -->
<div></div>
<div class="clickable"></div>
<div></div>
<div></div>
<div class="clickable"></div>
</div>
<div>
Click one of the red images above
</div>
</div>
Of course, if you're using jQuery, the .on() method can handle both the "add an event handler to all members of a set" option and the event delegation option in a single line.

Jquery Droppable Center Image in Div After Drop Event

Hey there,i'm creating a simple inventory using jQuery droppable. For now, it's like :
$(document).ready(function() {
$( ".weapon, .helmet" ).draggable({ revert: "invalid", cursor: "move" });
$( "#weapon_spot" ).droppable({accept: ".weapon"});
$( "#helmet_spot" ).droppable({accept: ".helmet"});
// make inventory slots droppable as well
$( ".inv_slot" ).droppable({accept: ".weapon"});
});
I'm kinda new to JQuery and have some trouble setting an image to be aligned inside a certain div. Everything(.weapon, .helmet etc) is a div. Inside them, there can be images. The divs are 70x70 and the images are of that size as well.
The css is like :
.inv_slot, #weapon_spot, #helmet_spot {
width: 70px;
padding: 10px;
height: 70px;
margin: 10px;
border: 1px solid black;
float: left;
text-align: center;
}
and the image inside a div is like :
<div class='inv_slot'>
<img class='weapon' src= "..." />
</div>
My problem is that when i drop an image to another div, it's not aligned in the center of the div, it's not locked and it can be moved inside it. It seems that i can use Drag.Move somehow to do that, but i can't find some good resource explaining that. Could you please help ? :)
EDIT : I have created a demo at http://jsfiddle.net/kzuRn/2/
Add a drop callback to the droppables and apply the style changes necessary. Because right now the item is still positioned absolutely it will not recognize your center css.
Something like this: WRONG (see below)
drop: function(ev, ui) {
$(this).css({position: 'static'})
}
I updated the fiddle. I was wrong before. this is the droppable, and ui.draggable is the draggable.
drop: function(ev, ui) {
$(this).append(ui.draggable.css('position','static'))
}

Categories

Resources