Moving a jQuery draggable() element to a new parent - javascript

I'm writing a simple card game in JavaScript, and I'd like to have a "card" img snap to its target when played. I'm accomplishing this by removing the img from its current parent and placing it in a new parent (the target). However, when I place the img in its new container with jQuery's .appendTo(), the card snaps to the corner of the screen.
See this demo for a working example.
Is there a reason the div snaps to the corner of the screen when it's moved to a new parent? I'm wondering if there are css properties that are being inherited/lost behind the scenes when I change the div's parent.
Any help would be appreciated.
- EDIT -
Additional information: while it has been suggested that I simply add this to my drop handler (which works) -
$(ui.draggable).css({'top' : '0', 'left' : '0'});
I'd like to .animate() to this position, so the snap isn't instantaneous. While the card does end up in the correct spot, it first snaps to the corner and then eases into the correct position. I'd like to avoid that first snap to the corner.

$(ui.draggable).css({'top' : '0', 'left' : '0'});
Sorry, I had to leave for work, but try this:
$("#target").droppable({
drop: function (event, ui) {
var offset = $('#target').offset()
var top = parseInt($(ui.draggable).css('top')) - offset.top;
var left = parseInt($(ui.draggable).css('left')) - offset.left;
$(ui.draggable).appendTo("#target");
$(ui.draggable).css({'top' : top, 'left' : left})
$(ui.draggable).animate({
top: 0,
left: 0
}, 500, function() {
// Animation complete.
});
}
});
http://jsfiddle.net/hsjvP/22/

Related

Position tooltip above mouse when room in viewport, otherwise below mouse

I am creating a tooltip and am having some problems with positioning it.
The tooltip is set to position: absolute, and I have a handler for mouse events that modifies it's top and left CSS depending on the pageX and pageY.
Now, I know I can just set the top to pageY and left to pageX. That will make the tooltip pop up to the bottom-right. I'm trying to orient it where it pops up on the top-right when there is room, but if it would be out of the viewport on the Y-axis, drop to the bottom-right position again.
At the moment, I'm stuck trying to get the tooltip to show to the top-right of the mouse. I don't even know where to begin detecting if it would be in the viewport. Can anyone point me in the right direction?
$('p').on('mouseenter', function(e) {
$(tt).css('top', e.pageY - $(tt).css('height'));
$(tt).css('left', e.pageX);
$(tt).appendTo('body');
}).on('mousemove', function(e) {
$(tt).css('top', e.pageY - $(tt).css('height'));
$(tt).css('left', e.pageX);
}).on('mouseleave', function(e) {
$(tt).detach();
});
Example on JSFiddle
There are many different ways to handle tooltips, especially when using jQuery. This method probably would not have been my first choice. However, the following changes should work how you intended.
var tt = document.createElement('div');
tt.id = "tt";
$('p').on('mouseenter', function(e) {
var curPos = $( this ).offset().top - $( window ).scrollTop();
var inView = (curPos < 250) ? 0 : 250;
$(tt).css('top', e.pageY - inView);
$(tt).css('left', e.pageX);
$(tt).append($( this ).attr("data-myId"));
$(tt).appendTo('body');
}).on('mousemove', function(e) {
$(tt).css('top', e.pageY - $(tt).css('height'));
$(tt).css('left', e.pageX);
}).on('mouseleave', function(e) {
$(tt).empty($( this ).attr("data-myId"));
$(tt).detach();
});
Full changes in JSFiddle.
I am taking advantage of jQuery's offset() and scrollTop() methods to estimate the position of the current element within the viewable area of the document.
According to jQuery's API documentation, the .offset() method
allows us to retrieve the current position of an element relative to
the document. The documentation also states that the vertical
scroll position (.scrollTop()) is the same as the number of pixels that are hidden
from view above the scrollable area.
We use both of these methods to our advantage and subtract the number of pixels above the scrollable area from the current position of the element relative to the document. One important thing to note is that the offset method returns an object with the properties top and left.
var curPos = $( this ).offset().top - $( window ).scrollTop();
Since you had the #tt id set to a static 250px height, we can check if the current element position relative to the viewable portion of the window is less than 250. If it is, then we subtract nothing and let the tool tip sit below the mouse position. If it is greater than 250 then we subtract 250px and the tool tip will be above the current mouse position.
I am not sure how you were intending to pull in the content for the tool tips, but I also added $(tt).append($( this ).attr("data-myId")); to use the data-myId value as the tool tip content and $(tt).empty($( this ).attr("data-myId")); to clear it on mouseleave. I hope this helps!

dojo.dnd.moveable with position:fixed

I try to use a dojo moveable with a fixed position in the browser window.
Unfortunatly everytime I move the div with the mouse the position is set to absolute. What can I do to make the div fixed ?
html:
<html>
<body>
<div id="moveMe" style="position:fixed;width:100px;height:100px;border:1px solid black;background-color:#00ff00;cursor:pointer;">bla</div>
<p>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>
test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>
test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>
test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>
test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>
</body>
</html>
script:
dojo.require("dojo.dnd.move");
dojo.ready(function(){
var pcm = new dojo.dnd.move.boxConstrainedMoveable(dojo.byId("moveMe"), {
box : dojo.window.getBox(),
within : true
});
});
Link to test:
http://jsfiddle.net/zPVdX/
cheers,
krater
position: fixed and position: absolute are two completely opposing methods used by the browser to determine how an element is positioned.
I'd first recommend reading up on the differences between them: http://css-tricks.com/absolute-relative-fixed-positioining-how-do-they-differ/
Hopefully now you will understand why Dojo draggable needs to set your element to an absolute position. This allows Dojo to visually move the draggable element via it's top: and left: properties.
Compare this with static positioning, which will attempt to anchor your element to a position relative to the current viewport.
If you add more detail on what are you visually trying to accomplish, there may be another solution.
You could use event 'MoveStop' on your DND (draggable element) in order to forcefully add position: fixed; at the END of your drag action. In this way you would be able to drag around your element using position: absolute; and have it have fix position when the drag is finished.
Some pesudo code
yourDnd.on('MoveStop', function (e) {
// Set position FIXED
domStyle.set(this.node, {
'position': 'fixed ',
});
});
More info on events can be found here:
http://livedocs.dojotoolkit.org/dojo/dnd
Regarding this hack I would not suggest you to change DOJO library as your change could be not safe and create bugs in other part of the framework.
I just got this working with:
dnd.on('MoveStart', function (e) {
var p = dojo.position(e.node, true);
var parent_position = dojo.position(e.node.parentNode, true)
dojo.style(e.node, "top", p.y - parent_position.y + "px");
dojo.style(e.node, "position", "absolute");
});
dnd.on('MoveStop', function (e) {
var p = dojo.position(e.node, false);
dojo.style(e.node, "top", p.y + "px");
dojo.style(e.node, "position", "fixed");
});

JQuery Draggable not working the way i want to

I have two horizontal divisions and i want to insert a slider in between then so that the height can be dynamically adjusted. The code am using is
<script type="text/javascript">
$(function() {
var stopFromTop = 58;
var stopToTop = 158;
var i = 0;
$("#handle").draggable({ axis: 'y',
start: function(event, ui) {
TopStart = $('#top').height();
BottomStart = $('#bottom').height();
},
drag: function(event, ui) {
$('#top').height( TopStart + (ui.position.top-ui.originalPosition.top) );
$('#bottom').height( BottomStart - (ui.position.top-ui.originalPosition.top) );
//$("#handle").css({"top":108 + "px" }).show();
//alert(ui.position.top);
},
containment: [0,stopFromTop ,0,stopToTop ]
});
});
</script>
But this is not working the way it should. The slider is not following the mouse when it is dragged. There must be something which I am doing wrong. Unable to get it!! :(
Here is the link to the page.
You could use jQuery UI's draggable element. Then simply calculate it offset from the top and set that as the top div's height. Then do some math to find the bottom div's height.
Edit
You have the slider's position set to relative, so basically it will appear right below the top div. Additionally you change its top value (which also moves it. So basically it is moving TWICE as much as it needs to). Either:
Set the sliders position to absolute (and play with top to position it right); <-- ALOT OF WORK, DO NOT ATTEMPT
Simply stop changing slider's top value
Seems to be a css problem with jquery. Changing the css property of separater to position:absolute fixed the problem.

How would I implement a vertical version of this horizontal dynamic header?

On The Economist website, there is a horizontal header that only appears after you scroll down the page once. See here:
http://www.economist.com/blogs/asiaview/2010/12/china_and_nobel_peace_prize
What I want is a vertical version of this that would come out of the left or right side of the page and expand over the page content that is already in place.
Anyone know of an existing plugin or how I could build something like that in jQuery?
Here's a simple jQuery plugin that should work for you:
(function($) {
$.fn.scrollToast = function(options) {
var settings = options || {};
var offset = settings.offset;
var toast = settings.toast;
var $toast = $(toast);
var hidden = true;
// prepare the toast:
$toast.css({
display: 'none',
position: 'fixed',
top: '0px',
left: '0px',
zIindex: '1',
overflow: 'hidden'
});
this.bind("scroll", function($event) {
var top = $(this).scrollTop();
if ((top >= offset && hidden) || (top < offset && !hidden)) {
hidden = !hidden;
$toast.animate(
{width: "toggle"});
}
});
};
})(jQuery);
Usage: $(window).scrollToast({toast: "#toast", offset: 50});, where #toast is a selector indicating the element to slide out, and offset is how long you want the user to scroll before the toast appears.
Notes:
Uses CSS position:fixed and an elevated z-index to make the toast element appear on top of other content.
When the target element is scrolled to a value equal to or beyond offset, the toast element is slid out (it is initially hidden).
When the target element is scrolled to a value less than offset the toast element is slid back in.
Could easily be extended to show the toast on the other edge of the screen or the top or bottom.
Will probably work on any scrollable element, but I've used $(window) because it seems to fit the use case you described.
See a working example here: http://jsfiddle.net/andrewwhitaker/56dTA/
Yes, it's pretty easy to build:
You create a:
<div id="hiddenmenu">
This Appears on scrolldown
</div>
This div should be absolute positionend, and display:none;
With the jQuery, on scroll-down you use $('#hiddenmenu').show();
That's pretty much it, if you need the full code, just ask and I'll post it.

Jump to content inside of a scrollable div

I got the following HTML:
<div style="height:200px;overflow-y:scroll;">
<table>.....</table>
</div>
With this setup I'm somewhat mimicking the expanded <select> control with #size attribute defined. So, that a user could select a row in the table. Is there a way, to make the table "jump up", so that the selected row appears to be at the top of the div and the vertical scrollbar scrolled to its position. I don't need the actual scrolling effect. The table should change it's position right away on row click.
This might work:
$("#scrollableDiv").animate({
scrollTop: 200 // scrolls to the bottom
}, 1000);
I suggest using scrollTop (or even animate it if you want).
$('div')[0].scrollTop = 200 //would set the scrollable div to 200px down.
http://jsfiddle.net/8mepH/
Here is an modified extract of the code used in:
http://www.balupton.com/sandbox/jquery-scrollto/demo/
To do what you want:
// Fetch the scrollable div
$container = $('#scrollable');
// Fetch the target div
$target = $('#target');
// Prepare the Inline Element of the Container
var $inline = $('<span/>').css({
'position': 'absolute',
'top': '0px',
'left': '0px'
});
var position = $container.css('position');
// Insert the Inline Element of the Container
$container.css('position','relative');
$inline.appendTo($container);
// Determine the Offsets
var startOffset = $inline.offset().top,
targetOffset = $target.offset().top,
offsetDifference = targetOffset - startOffset;
// Perform the jump
$container.css('scrollTop',offsetDifference+'px')
We add a inline here to ensure we get the correct start position within the scrollable area. We use a offset difference so if you want to do animations it animations from the start position, rather than jumping somewhere else.

Categories

Resources