I'm working on an interface where users can drop "widgets" on "droppable zones" in the page.
The widgets are stored in a div absolutely positionned in the page (on the left, with z-index:1)
The droppables zones are in another div in the page.
The problem is :
When i drag a widget from the left column to a droppable zone in the page, the droppable event is catch even through the left column div. I want to stop the droppable event when the user drags over the left colum, but keep the event when the user is out of the left column.
HTML
<div id="left">
<div class="dragMe">Drop me on Yellow</div>
<div class="dragMe">Drop me on Yellow</div>
<div class="dragMe">Drop me on Yellow</div>
<div class="dragMe">Drop me on Yellow</div>
</div>
<div id="right">
<div class="dropOnMe"></div>
<div class="dropOnMe"></div>
<div class="dropOnMe"></div>
<div class="dropOnMe"></div>
<div class="dropOnMe"></div>
<div class="dropOnMe"></div>
</div>
CSS
#left {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 220px;
z-index: 1;
background-color: gray;
padding: 10px;
}
.dropOnMe {
width: 500px;
height: 200px;
display: inline-block;
background-color: yellow;
}
.dragMe {
height: 20px;
width: 200px;
margin-bottom: 5px;
border: 1px solid red;
font-size: 13px;
background-color: white;
text-align: center;
cursor: move;
font-family: tahoma;
}
.ui-droppable-hover {
outline: 3px solid red;
}
JS
$(function() {
$('#left .dragMe').draggable(
{
helper: 'clone',
opacity: 0.5,
appendTo: 'body',
zIndex: 11
}
);
$('#right .dropOnMe').droppable(
{
drop: function( event, ui ) {
console.log(event);
}
}
);
});
Check example : http://jsbin.com/judajucuxu/1/edit?html,output
Any idea ?
Thanks.
The problem is not in JavaScript code. The problem is in your CSS.
Your left side is always a part of droppable area, because positioned absolutely.
It woks if you fix it in this example.
#left {
position: relative;
}
Besides, I wouldn't recommend using jQuery UI library for that, because all contemporary browsers has HTML Drag and Drop API.
EDIT 1:
You could also move the right on the width of the left container, to prevent interaction:
#right{
margin-left: 230px;
}
EDIT 2:
You could also do fancy stuff, once you say you can't change HTML.
Try to detect the cursor offset and decided if you ready to drop your element:
drop: function( event, ui ) {
if (event.pageX > $('#left').width() + 100) {
console.log(event);
}
}
Example
Try this code..
$('#left .dragMe').draggable({
refreshPositions: true
});
Related
I am trying to attach a div to the cursor. The div only appears when it is over a specific box, and depending on the box it hovers over it is populated with an html message.
I've got the cursor attached to the mouse, but when I hover over any of the boxes (which also turn white when hovered over,) the div and the box "glitch" really hard. I assume this has to do something with the z-index, but I can't figure it out.
function mouseHandler(ev) {
document.getElementById('boxshadow').style.transform = 'translateY(' + (ev.clientY) + 'px)';
document.getElementById('boxshadow').style.transform += 'translateX(' + (ev.clientX) + 'px)';
}
document.getElementById("talk").addEventListener("mousemove", mouseHandler)
document.getElementById("time").addEventListener("mousemove", mouseHandler)
document.getElementById("chat").addEventListener("mousemove", mouseHandler)
$("#talk").mouseleave(function() {
$("#boxshadow").hide()
});
$("#talk").mouseover(function() {
$("#boxshadow").show()
$("#boxshadow").html("Message1")
});
$("#time").mouseleave(function() {
$("#boxshadow").hide()
});
$("#time").mouseover(function() {
$("#boxshadow").show()
$("#boxshadow").html("Message2")
});
$("#chat").mouseleave(function() {
$("#boxshadow").hide()
});
$("#chat").mouseover(function() {
$("#boxshadow").show()
$("#boxshadow").html("Message3")
});
.scrolltext {
position: relative;
border-bottom: 2px solid black;
letter-spacing: -15px;
white-space: nowrap;
line-height: 80%;
overflow-y: hidden;
overflow-x: scroll;
padding: 5px;
height: 160px;
width: 100%;
font-size: 200px;
z-index: 1;
}
#talk:hover {
background-color: white;
}
#time:hover {
background-color: white;
}
#chat:hover {
background-color: white;
}
#boxshadow {
width: 200px;
height: 200px;
background-color: red;
border: 1px solid black;
position: absolute;
z-index: 100000000000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div id="boxshadow"></div>
<div class="scrolltext" id="talk">
<p>A TALK WITH A GOOD FRIEND</p>
</div>
<div class="scrolltext" id="time">
<p>A LOVELY TIME WITH A GOOD FRIEND </p>
</div>
<div class="scrolltext" id="chat">
<p>A CHAT WITH A GOOD FRIEND </p>
</div>
</div>
So I think what's happening here is that your cursor can't be hovering over the div if the #boxshadow element is in the way. So the cursor triggers the box because it's over the div, then immediately isn't over the div anymore because it's over the box. So it's flipping back and forth... forever.
To avoid this, add the css property pointer-events: none; to the box. The browser will basically ignore the box when it's asking whether the mouse is "over" the div, and that should stop the glitching.
NB: If you want the user to be able to click on something in the box (obviously not an option right now, but I don't know what your plans are), with pointer-events: none the click will pass through to the div below.
I've got a jQuery fiddle using the jQuery UI draggable to demonstrate this problem. Here is the HTML:
<div id="container">
<div id="components">
<p>
Components: Click to add a component.
</p>
<div class="component">
<div class="component-title">
One
</div>
</div>
<div class="component">
<div class="component-title">
Two
</div>
</div>
<div class="component">
<div class="component-title">
Three
</div>
</div>
</div>
<div id="workspace">
<div id="pdc">
</div>
</div>
</div>
Here is the CSS:
#workspace {
padding-top: 20px;
clear: both;
}
#pdc {
border: 1px solid #000000;
border-radius: 5px;
width: 300px;
height: 150px;
position: relative;
}
.component-title {
cursor: default;
}
#pdc .component-title {
cursor: move;
}
.component {
border: 1px solid #000000;
border-radius: 5px;
text-align: center;
width: 98px;
height: 48px;
}
#components .component {
float: left;
margin: 0 12px 0 0;
}
#pdc .component {
cursor: move;
display: inline-block;
}
.component-delete {
float: right;
color: pink;
margin-right: 5px;
cursor: pointer;
}
.component-delete:hover {
color: red;
}
Here is the jQuery:
$(document).ready(function() {
$('.component').click(function(){
var lastpdccomponent, html = $(this).clone().prepend('<div class="component-delete">X</div>');
if ($('#pdc').children().length > 0) {
lastpdccomponent = $('#pdc').children().last();
$('#pdc').append(html);
$('#pdc').children().last().position({
my: "left top",
at: "left bottom",
of: lastpdccomponent
});
} else {
$('#pdc').append(html);
}
$('#pdc .component').draggable({
containment: '#pdc',
scroll: false,
grid: [50, 50]
});
});
$('#pdc').on('click', '.component-delete', function() {
$(this).parent().remove();
});
});
It's set up so that if you click a component (One, Two, or Three), the component is cloned and added to the "pdc" div as in the image below:
If you drag the second and third components so that they are in a horizontal row with the first component:
and then delete the first component by clicking the red "X", the other components move outside the container as shown in this image:
I've experimented with other display options for the components, like "inline-block", and it fixes the issue with deleting the first in a horizontal row of components, but introduces a new problem when the first in a vertical row of components is deleted; in that case, the remaining elements move off to the left of the container.
How can I prevent the other components from moving outside the container when the first component in the row is deleted?
The position of the .component's is relative and thus is being calculated based on the preceding element. Once you remove the first one, the position for the follow ups is getting calculated not correctly any more. In order to prevent that behavior, just add position:absolute; to #pdc .component{ in css to make the calculation of position of the components independent from each other, see snippet:
UPDATE I see when there is a scrollbar, positioning of the elements is getting messed up, so in order to solve this issue add collision: 'none' to
$('#pdc').children().last().position({
my: "left top",
at: "left bottom",
of: lastpdccomponent,
collision: 'none'
});
See updated snippet:
$(document).ready(function() {
$('.component').click(function(){
var lastpdccomponent, html = $(this).clone().prepend('<div class="component-delete">X</div>');
if ($('#pdc').children().length > 0) {
lastpdccomponent = $('#pdc').children().last();
$('#pdc').append(html);
$('#pdc').children().last().position({
my: "left top",
at: "left bottom",
of: lastpdccomponent,
collision: 'none'
});
} else {
$('#pdc').append(html);
}
$('#pdc .component').draggable({
containment: '#pdc',
scroll: false,
grid: [50, 50]
});
});
$('#pdc').on('click', '.component-delete', function() {
$(this).parent().remove();
});
});
#workspace {
padding-top: 20px;
clear: both;
}
#pdc {
border: 1px solid #000000;
border-radius: 5px;
width: 300px;
height: 150px;
position: relative;
}
.component-title {
cursor: default;
}
#pdc .component-title {
cursor: move;
}
.component {
border: 1px solid #000000;
border-radius: 5px;
text-align: center;
width: 98px;
height: 48px;
}
#components .component {
float: left;
margin: 0 12px 0 0;
}
#pdc .component {
cursor: move;
position:absolute;
}
.component-delete {
float: right;
color: pink;
margin-right: 5px;
cursor: pointer;
}
.component-delete:hover {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
<div id="container">
<div id="components">
<p>
Components: Click to add a component.
</p>
<div class="component">
<div class="component-title">
One
</div>
</div>
<div class="component">
<div class="component-title">
Two
</div>
</div>
<div class="component">
<div class="component-title">
Three
</div>
</div>
</div>
<div id="workspace">
<div id="pdc">
</div>
</div>
</div>
Set you .component to position: absolute; and this should fix it since your container #pdc is already set to position: relative;. When you delete the element that the others are positioned relative off of everything goes crazy, but when they are absolutely positioned they should stay put.
Also set the #components .component to position: static; because you don't need those positioned.
See this fiddle for a demo
CSS Changes:
.component {
position: absolute; /*Add this*/
border: 1px solid #000000;
border-radius: 5px;
text-align: center;
width: 98px;
height: 48px;
}
#components .component {
position: static; /*Add this*/
float: left;
margin: 0 12px 0 0;
}
The problem is that on click of .component-delete, the components don't get 'reset' to their default positions, and have an inline height of -50px (and a left offset).
You can resolve this by resetting their positions manually, adding:
$(this).parent().siblings().css('top', '0');
$(this).parent().siblings().css('left', '0');
To the deletion function, resulting in the following:
$('#pdc').on('click', '.component-delete', function() {
$(this).parent().siblings().css('top', '0');
$(this).parent().siblings().css('left', '0');
$(this).parent().remove();
});
This will make the second and third element move two the left and stack vertically when deleting the first element, as can be seen working here.
Unfortunately I don't think it's possible to keep the remaining two elements in a horizontal line on deletion, as if you omit resetting the height position, the second element would take on the height offset from the first. Hopefully this is still sufficient.
Hope this helps! :)
I am trying to create an effect that when you roll over an image a pointer will point towards it. The same as used in this website about half way down: https://thecleansekitchen.com.au/
I'm not sure where to begin or if there are any JQuery or plugins out there for this but I cant find any?
Any help appreciated.
I'm sure there are some jQuery plugins out there that do this but that's probably unnecessary. You can accomplish this pretty easily with some basic HTML, CSS and JavaScript.
I created a JSFiddle to try to help you get started. https://jsfiddle.net/x823m6ff/
Note that the above is very crude and you'll definitely need to massage it for your needs but hopefully it will help you start down the right path.
I'll lay out the code here as well to explain.
HTML:
<div class="container">
<div class="block">
<div class="arrow arrow-down"></div>
</div>
<div class="block">
<div class="arrow arrow-down"></div>
</div>
<div class="block">
<div class="arrow arrow-down"></div>
</div>
</div>
For the HTML, I created a container with three blocks (like your screenshot). Each block has a child arrow element that is hidden through CSS.
CSS:
.container {
width: 960px;
margin: 0 auto;
}
.block {
width: 100px;
height: 150px;
background-color: #000;
float: left;
margin-right: 20px;
position: relative;
}
.arrow {
display: none;
position: absolute;
top: 0;
left: 25%;
}
.arrow-down {
width: 0;
height: 0;
border-left: 25px solid transparent;
border-right: 25px solid transparent;
border-top: 25px solid #FFF;
}
The CSS sets up some widths and heights for our blocks and creates the arrow elements. We're positioning these arrow elements relative to each block and putting them at the top middle of each block.
JavaScript:
$(document).ready(function() {
$('.block').hover(function() {
$(this).find('.arrow').show();
}, function() {
$(this).find('.arrow').hide();
});
});
The above JavaScript is very simple and basically just listens for a mouse hover over our block and shows / hides our arrow depending on the state of the user's mouse over the block.
I am simulating a pop up window that fades the background out. I do this by simply toggling a div that fills the whole screen. I would like to be able to close the pop up by clicking the outside background, but not when you click on the new content area, which is what is currently happening. My code:
JS:
function popbox() {
$('#overbox').toggle();
}
HTML:
<div class="popbox" onclick="popbox()"> Click Here </div>
<div id="overbox" onclick="popbox()">
<div id="infobox1">
<p>This is a new box</p>
<br />
<p>hello </p>
<br/><br/>
<p style="color:blue;text-align:center;cursor:pointer;" onclick="popbox()">close</p>
</div><!-- end infobox1 -->
</div> <!-- end overbox -->
CSS:
#overbox {
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background: rgba(64, 64, 64, 0.5);
z-index: 999999;
display: none;
}
#infobox1 {
margin: auto;
position: absolute;
left: 35%;
top: 20%;
height: 300px;
width: 400px;
background-color: white;
border: 1px solid red;
}
.popbox {
cursor: pointer;
color: black;
border: 1px solid gray;
padding: 5px; 10px;
background: ghostwhite;
display: inline-block;
}
JSFiddle link: http://jsfiddle.net/RrJsC/
Again, I want it to toggle only when you click the faded background or "close" (which isnt working in the jsfiddle but is on my site), but not when you click inside the white box that it contains.
After some research it seems like I might be looking for .stopPropagation(), but I haven't been able to get it to work at all.
I got it to work using jQuery's event handlers:
$('#container').on('click', '.popbox, #overbox', function(e){
$('#overbox').toggle();
});
$('#container').on('click', '#infobox1', function(e){
e.stopPropagation();
});
I replaced document with '#container' for better performance. You should wrap all your divs in <div id="container">...</div> so the the callback doesn't fire on the dom every time there is a click (even thought that callback is only called when the selector matches).
You'll also need to get rid of your onclick html attributes, because they will throw an error if that function is not defined.
I hope I understand well your problem.
If it is the case, you should have this:
<div id="overbox">
instead of this:
<div id="overbox" onclick="popbox()">
here is the updated jsfiddle
I'm trying to have a draggable div which can also be dragged from a textarea within it.
html:
<div id="divContainer">
<textarea id="text"></textarea>
</div>
css:
#divContainer {
position: absolute;
left: 10px;
top: 10px;
width: 100px;
height: 100px;
background-color: blue;
}
#text {
position: absolute;
left: 5px;
top: 5px;
width: 50px;
height: 50px;
background-color: green;
}
jquery:
$("#divContainer").draggable();
I can drag the div if I drag by clicking in the div area, but not if I click into the textarea area.
Is there a way to solve this ?
Here is the jsFiddle
Check Out this fiddle perfect for you
FIDDLE
Code:
HTML:
<div>
<textarea name="ta" id="ta" cols="30" rows="10"></textarea>
</div>
CSS:
div {
background-color:#aaa;
padding: 4px;
text-align: center;
position:relative;
}
JS:
$('div').draggable({
cancel: "ta",
start: function (){
$('#ta').focus();
} ,
stop: function (){
$('#ta').focus();
}
});
You can use the cancel option, setting it to '', similar to this:
$("#divContainer").draggable({ cancel: '' });
DEMO - Using the cancel option
Though this works for dragging, it causes other issues.
You are now unable to click into the textarea itself as draggable takes over the event.
You would have to write some custom code now to work around this.
Using an overlay is also a problem to implement as you now have to deal with when to place it over the div and when not.
I would recommend to leave the default functionality of any elements inside the draggable div as is instead of "hacking" around them.
Possible Alternative
A more user-friendly approach might be to add a frame-like border to the div or a header-like border at the top to enable to user to drag the div.
Using HTML similar to this:
<div id="divContainer">
<div class="dragger"></div>
<textarea id="text"></textarea>
</div>
Giving the dragger the following css:
.dragger {
border: none;
background-color: gray;
height: 15px;
width: 100%;
display: block;
}
and updating your textarea css to not use absolute positioning but instead use margins to specify the 5px on the left and top.
#text {
width: 50px;
height: 50px;
background-color: green;
margin-top: 5px;
margin-left: 5px;
}
You then can implement the handle option similar to this:
$("#divContainer").draggable({
handle: '.dragger'
});
DEMO - Using a header to drag
I'm not sure if this is a solution you can use or not but it would be one option.
Hope this help:
Demo
JQuery:
$(document).ready(function(){
$('#move').css('top',$("#text").css('top'));
$('#move').css('left', $("#text").css('left'));
$("#divContainer").draggable();
$("#move").draggable({drag:function(event,ui){
$('#text').css('top',$("#move").css('top'));
$('#text').css('left', $("#move").css('left'));
},grid:[1,1],stop:function(){
$('#move').css('top',$("#text").css('top'));
$('#move').css('left', $("#text").css('left'));
}});
});