Hi I use the jQuery UI Resizable and jQuery UI Draggable for all of my three div elements.
The basic Dom tree looks like this:
So basically blue and red are siblings and orange is the parent.
If I resize blue vertically then red automatically changes its position that the vertical space between them stays the same. This problem does not apply to Draggable, so I can change the vertical distance by dragging blue and red around but every time I resize blue vertically red moves too.
If I make blue bigger vertically -> red moves down, I do not want that optimatically it would be that you can make blue bigger vertically until it hits the border of red and then thats it.
I tried several .css styles but nothing works
Here is the current .css that I use:
Hi thanks for all your comments, I could find the solution:
JQuery UI resizable adds the .css attribute position:relative; to every resizable <div> element.
I explain it to myself like this:
"relative: The element is positioned relative to its normal position, so 'bottom:20px' adds 20 pixels to the element's BOTTOM position"
This means the normal position of red is directely under blue, but because of draggable we added, lets say 20px of space by dragging red down.
If you resize blue, then this 20px of space will be preserved, by moving red down.
When we use position: absolute !important; then red is always positioned
"relative to its first positioned (not static) ancestor element"
which is orange
/*overrides the '.ui-resizable' 'position:relative;' this helps that after resizing the position of the element
get placed relative to its parent <div>*/
position: absolute !important;
This code should give you some ideas. It works for resizing the blue box and when it hits the top of the red box it stops. So first see that you can not resize the blue since it starts flush to the red. Then MOVE red down a little diagonally to the bottom right. Now, if you resize the blue, it will hit the constraint of the red box.
I showed only one side of the constraint (from blue to red) to see if this helps before applying it to (red to blue). Actually, there would be at least 4 constraints: top, bottom, left, right.
Pay attention to the two css position attributes I added.
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>OOIndex</title>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
<link href="~/Content/themes/base/jquery-ui.css" rel="stylesheet" />
<style>
/*div {
outline: 1px solid black;
height: 100%;
width: 100%;
height: 200px;
width: 200px;
min-height: 30px;
min-width: 500px;
}*/
.resizable {
width: 150px;
height: 150px;
padding: 0.5em;
}
.orange {
height: 100%;
width: 100%;
background-color: orange;
/*added*/
position: absolute;
}
.blue {
background-color: blue;
width: 150px;
height: 150px;
padding: 0.5em;
}
.red {
background-color: red;
width: 150px;
height: 150px;
padding: 0.5em;
/*added*/
position: fixed;
}
</style>
<script type="text/javascript">
$(function () {
var targetRed = $('.red').position();
$("#redPos").text("left " + targetRed.left + " top" + targetRed.top)
var targetBlue = $('.blue').position();
$("#bluePos").text("left " + targetBlue.left + " top" + targetBlue.top)
$('#blueResiz').resizable({
resize: function (event, ui) {
targetPos = $('.red').position();
$("#redPos").text("left " + targetPos.left + " top" + targetPos.top)
var added = ui.position.top + ui.size.height;
$("#bluePos").text("top " + ui.position.top + " height" + ui.size.height + " total " + added)
//if blue
if (ui.position.top + ui.size.height < targetPos.top) {
$(this).resizable({ maxHeight: targetPos.top - 20 });
}
}
});
$('#redDrag').draggable({
drag: function (event, ui) {
targetPos = $('.red').position();
}
})
})
</script>
</head>
<body class="orange">
<div class="blue draggable" id="blueResiz">
<div id="bluePos"></div>
</div>
<div class="red draggable" id="redDrag">
<div id="redPos"></div>
</div>
</body>
</html>
Related
I have read a lot of the questions on here but can't find one that fixes this. I have programmed a div to follow my cursor. I only want it to appear when the cursor is over #backgroundiv. I have got it working but it sometimes randomly flickers on chrome and disappears entirely on firefox. Even more randomly is it sometimes appears to work and then starts flickering. I have tried a variety of things from hover to mouseenter/mouseover but nothing seems to work.
What I want is for #newdot to appear when the cursor is over #backgroundiv and then follow the cursor around the div. Any help would be much appreciated.
//hide dot when leaves the page
$(document).ready(function() {
$("#backgroundiv").hover(function() {
$("#newdot").removeClass("hide");
}, function() {
$("#newdot").addClass("hide");
});
});
//div follows the cursor
$("#backgroundiv").on('mousemove', function(e) {
//below centres the div
var newdotwidth = $("#newdot").width() / 2;
$('#newdot').css({
left: e.pageX - newdotwidth,
top: e.pageY - newdotwidth
});
});
//tried below too but it doesn't work
/*$(document).ready(function(){
$("#backgroundiv").mouseenter(function(){
$("#newdot").removeClass("hide");
});
$("#backgroundiv").mouseout(function(){
$("#newdot").addClass("hide");
});
}); */
#backgroundiv {
width: 400px;
height: 400px;
background-color: blue;
z-index: 1;
}
#newdot {
width: 40px;
height: 40px;
background-color: red;
position: absolute;
z-index: 2;
}
.hide {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="newdot"></div>
<div id="backgroundiv"></div>
There is not issue but a logical behavior, when you hover on the blue div you trigger mouseenter so you remove the class and you see the red one BUT when you hover the red one you trigger mouseleave from the blue div thus you add the class and you hide the red one. Now the red is hidden you trigger again the mouseenter on the blue div and you remove the class again and the red div is shown, and so on ... this is the flicker.
To avoid this you can consider the hover on the red box to make the red box appear on its hover when you lose the hover from the blue one.
$(document).ready(function() {
$("#backgroundiv").hover(function() {
$("#newdot").removeClass("hide");
}, function() {
$("#newdot").addClass("hide");
});
});
//div follows the cursor
$("#backgroundiv").on('mousemove', function(e) {
//below centres the div
var newdotwidth = $("#newdot").width() / 2;
$('#newdot').css({
left: e.pageX - newdotwidth,
top: e.pageY - newdotwidth
});
});
#backgroundiv {
width: 400px;
height: 400px;
background-color: blue;
z-index: 1;
}
#newdot {
width: 40px;
height: 40px;
background-color: red;
position: absolute;
z-index: 2;
}
.hide {
display: none;
}
/* Added this code */
#newdot:hover {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="newdot">
</div>
<div id="backgroundiv">
</div>
I have 2 divs positioned next to each other, and a background div. We'll call the background div "bg div". Whenever one of the 2 divs get selected, the bg div gets positioned on top of the selected div with a transition. Basically, something like a segmented controller.
The next step I want to do is, I want to make the bg div draggable. If it gets dragged, but not all the way to either side, then it should snap to whichever side the bg div is mostly at.
I'm looking for something like this:
When I set the bg div to be draggable, (using JQuery UI) it wasn't draggable. Only when I removed z-index: -1 did it become draggable. It also didn't snap to either side. It only snapped when the bg div got dragged basically all the way. Also, when I drag it, it has a weird effect to it. It waits a bit then drags. I think that's because the transition.
Problems
How can I make it draggable with of index: -1?
How can I make it snap to whichever side the bg div is mostly at?
How can I make it have a transition without working weird?
Without issues, but not draggable functionality: JSFiddle
With issues: JSFiddle
$('#bckgrnd').draggable({
axis: "x",
containment: "parent",
snap: ".labels"
});
#radios {
position: relative;
width: 370px;
}
input {
display: none;
}
#bckgrnd,
#bckgrndClear,
.labels {
width: 50%;
height: 30px;
text-align: center;
display: inline-block;
float: left;
padding-top: 10px;
cursor: pointer;
}
.labels {
outline: 1px solid green;
}
#bckgrnd {
background-color: orange;
position: absolute;
left: 0;
top: 0;
transition: left linear 0.3s;
}
#rad1:checked ~ #bckgrnd {
left: 0;
}
#rad2:checked ~ #bckgrnd {
left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="radios">
<input id="rad1" type="radio" name="radioBtn" checked>
<label class="labels" for="rad1">First Option</label>
<input id="rad2" type="radio" name="radioBtn">
<label class="labels" for="rad2">Second Option</label>
<div id="bckgrnd"></div>
</div>
Working solution: http://jsfiddle.net/6j0538cr/ (I know you wont use it :))
How can I make it draggable with of index: -1?
Add two elements one that hold the label with 'pointer-events:none;' which will ignore all mouse events and 'z-index:3',
And second that will be the 'button' and will have 'z-index:1'.
Like that you will have one label that ignores all mouse events and float above all the elements with z-index:3, and the 'background' will still be draggable
How can I make it snap to whichever side the bg div is mostly at?
You can calculate it very easily using 'offset' and 'width' functions like so
//calculating the middle of the 'background'
var backgroundX = $('#bckgrnd').offset().left;
var backgroundWidth = $('#bckgrnd').outerWidth();
var backgroundMiddle = backgroundX + (backgroundWidth/2);
//calculating the middle of the radios on the page
var radiosX = $('#radios').offset().left;
var radiosWidth = $('#radios').outerWidth();
var radiosMiddle = radiosX + (radiosWidth/2);
//compare the two
if(radiosMiddle > backgroundMiddle){
//closer to the left
}else{
//closer to the right
}
How can I make it have a transition without working weird?
You can set the transition using jQuery 'animate' instad of mixing css and js animation.
draggable with index -1: Have a container div for the whole thing (radios?) trapping mouse events. mousedown you record the mouse x value. mousemove (with button down I suppose) you calculate the "delta" from current mouse x to mousedown x, and add that to the original x value of the thing you are "dragging".
snapping: just using min / max function to limit the delta, but it sounds like some animation is there even for the "snap". So for a mouse up within a certain end zone range, fire that animation to "snap" to one side or the other.
Also, the click inside certain bounds close to the edge fires that same snap.
I've could probably done this using <input> radio elements...
But any way on submit you can send the data-* value.
Here's my take:
$(".io-toggler").each(function(){
var io = $(this).data("io"),
$opts = $(this).find(".io-options"),
$clon = $opts.clone(),
$span = $clon.find("span"),
width = $opts.width()/2;
$(this).append($clon);
function swap(x) {
$clon.stop().animate({left: x}, 150);
$span.stop().animate({left: -x}, 150);
$(this).data("io", x===0 ? 0 : 1);
}
$clon.draggable({
axis:"x",
containment:"parent",
drag:function(evt, ui){
$span.css({left: -ui.position.left});
},
stop:function(evt, ui){
swap( ui.position.left < width/2 ? 0 : width );
}
});
$opts.on("click", function(){
swap( $clon.position().left>0 ? 0 : width );
});
// Read and set initial predefined data-io
if(!!io)$opts.trigger("click");
// on submit read $(".io-toggler").data("io") value
});
.io-toggler{
cursor:pointer;
display:inline-block;
position:relative;
font:20px/1.5 sans-serif;
background:url(http://i.stack.imgur.com/XVCAQ.png);
color:#fff;
border:4px solid transparent;
border-radius: 50px;
user-select:none;
-webkit-user-select:none;
-webkit-touch-callout:none;
}
.io-options{
border-radius:50px;
top:0;
left:0;
overflow:hidden;
}
.io-options span{
position:relative;
text-align:center;
display:inline-block;
padding: 3px 35px;
}
/* the jQ clone */
.io-options + .io-options{
position:absolute;
background:#fff;
width:50%;
height:100%;
white-space:nowrap;
}
.io-options + .io-options span{
color:#006cff;
}
<link href="https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<span class="io-toggler" data-io="0">
<span class="io-options">
<span>Thing1</span>
<span>Thing2</span>
</span>
</span>
<br><br>
<span class="io-toggler" data-io="1">
<span class="io-options">
<span>Yes</span>
<span>No</span>
</span>
</span>
I'm pretty new to javascript and I'm trying to create a horizontal scrolling div :-
JSfiddle
As you can see the menu links go to each colour but I would like to put this inside a container which is 250x250px so only 1 colour is visible, then you click on whichever link and it scrolls to that colour.
Hope someone can help me with a few pointers.
Thanks!
jQuery(document).ready(function ($) {
$(".scroll").click(function (event) {
event.preventDefault();
$('html,body').animate({
scrollLeft: $(this.hash).offset().left
}, 200);
});
});
.container {
white-space: nowrap;
}
.child-element {
min-width: 250px;
display: inline-block;
height: 250px;
}
.child1 {
background-color: purple;
}
.child2 {
background-color: orange;
}
.child3 {
background-color: black;
}
.child4 {
background-color: green;
}
.child5 {
background-color: blue;
}
.child6 {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
PURPLE
ORANGE
BLACK
GREEN
BLUE
RED
<div class="container">
<div id="purple" class="child-element child1"></div>
<div id="orange" class="child-element child2"></div>
<div id="black" class="child-element child3"></div>
<div id="green" class="child-element child4"></div>
<div id="blue" class="child-element child5"></div>
<div id="red" class="child-element child6"></div>
</div>
As #Script47 mentioned, you'll want to apply overflow-x as a CSS property to your element, in addition the width (to act as a viewport). Here's what your final CSS might look like:
.container {
white-space: nowrap;
overflow-x: scroll;
width: 250px;
position: relative;
}
After that, you'll need to modify your JS slightly. You'll still want to scroll to the offset of the element, but you'll also need to take into account your current scroll position.
(To clarify, if you clicked orange - which has an offset initially of 250px, post-animation, the offset for orange would be0px, and black would be250px. If you then click black, it will attempt to scroll to 250px, which is the orange element.)
Here's what the updated JS might look like:
jQuery(document).ready(function ($) {
$(".scroll").click(function (event) {
var current = $('.container').scrollLeft();
var left = $(this.hash).position().left;
event.preventDefault();
$('.container').animate({
scrollLeft: current + left
}, 200);
});
});
A fiddle to demonstrate: https://jsfiddle.net/bpxkdb86/4/
For the fiddle, I removed physical white-space in the HTML (to prevent the divs from having space between them) using <!-- comments -->, and also added position: relative to the containing element (to use position)
A CSS solution, try adding this to you element in CSS,
overflow-x: scroll;
This, should do it for you.
You need two changes for this to work.
First, add height and width for the container and then set overflow in css.
width:250px;
height:250px;
overflow: auto;
Second update jquery to animate the container, now it is animating the body.
$('.single-box').animate({
JSFiddle is avaialble in the following link
https://jsfiddle.net/jym7q0Lu/
just use a css if you want your div to be scrollable..
.container {
white-space: nowrap;
overflow-x: scroll;
width: 250px;
position: relative;
}
I made a div over another div to create a border.
Here is an example:
Now I have a problem: if I put the mouse over the image I get the focus on the div with the border only (for ex., if I want right click and save img) but the div is empty all the time (is used only for the border) how i can ignore the center part of the div?
I used a div because I place the border over the image/other stuff and I can't have the same result using the original border (is placed outside the image and I get a white space from the border and the image).
In this jsfiddle the dimension aren't right. (I place the border with js code)
img = $('<div style="position:absolute; width: ' + ($(this) .outerWidth(true) +
leagueBorders[templeague].width) + 'px; height: ' + ($(this) .outerHeight(true) +
leagueBorders[templeague].height) + 'px; max-width: none; top: '+
($(this).position().top + leagueBorders[templeague].top) +'px; left: '+
($(this).position().left + leagueBorders[templeague].left) +'px;"
class="'+leagueBorders[templeague].classe+'"></div>');`
But you can easily see the problem. If you right click on the image you get the right click menu of a empty space instead of the image options.
if I a text with a scroll bar (instead of the image) I can't use the scroll bar.
A div isn't enmpty just because you don't see anything in it. A div can have a transparent content, it doesn't mean that ti's empty. It's like a transparent layer. That's why it takes the focus. You should use css border properties to fit your borders to the image. Or, you should wrap your image in a container (a div) and apply specific css rules to this container, so that your borders will fit.
You need to fix your HTML tags and use CSS to do all the graphical work.
Make sure img tag is inside div and then use the following CSS.
SEE PICTURE HERE
.rank-Platino {
overflow: hidden;
border: 15px solid transparent;
border-image-slice: 95 80 95 80;
border-image-width: 50px 50px 50px 50px;
border-image-outset: 0px 0px 0px 0px;
border-image-repeat: stretch stretch;
border-image-source: url("https://dl.dropboxusercontent.com/u/30396291/LOL/border/plat-border.png");
margin: 6px;
}
<a class="avatar">
<div style="position:absolute; width: 90px; max-width: none; top: 0px; left: 0px" class="rank-Platino rank-border">
<img height=163 width=90 class="user_summoner_icon PLATINUM rank-border"
src="http://www.mobafire.com/images/champion/skins/portrait/rammus-full-metal.jpg"></div>
</a>
Use CSS when working with borders, like this:
border-size:2px;
border-style:solid;
border-color:black;
According to w3schools, the relative position value is defined as follows.
relative - The element is positioned relative to its normal position, so "left:20" adds 20 pixels to the element's LEFT position.
I know that I can get the DOM object of whatever I positioned relatively and using that, I can get the left or top position w/ respect to the origin.
My question is, how can I get the "normal" position?
Thanks,
mj
Maybe, I misunderstand your question, but wouldn't this just be simple subtraction of the relative offset?
"normal" position is where the element will be positioned with left:0; top:0;. You can get this position by substracting the offset from the current position (tested in Chrome):
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
<style type="text/css">
#container { width: 100px; height: 100px; margin: 100px auto; border: 1px solid red; }
#item { position: relative; top: 10px; left: 10px; width: 80px; height: 80px; border: 1px solid green; }
</style>
<script type="text/javascript">
window.onload = function () {
var container = document.getElementById('container');
var item = document.getElementById('item');
var computed = window.getComputedStyle(item);
item.innerHTML = 'Normal: (' + (item.offsetLeft - parseInt(computed.left))
+ ', ' + (item.offsetTop - parseInt(computed.top) + ')');
};
</script>
</head>
<body>
<div id="container"><div id="item"></div></div>
</body>
</html>
to normal position just set position value to: static
position:static