jQuery draggable moves when dropped - javascript

I have set up a simple drag and drop interface which implements the clone functionality. The issue I have is that when the element is dragged to the main canvas and then dropped, it suddenly shifts to the right, rather than dropping exactly where I drag it.
Here is the javascript:
$(function() {
var x = null;
$("#draggable").draggable({
helper: 'clone',
cursor: 'move',
snap: '.snap-target'
});
$("#canvas").droppable({
drop: function(e, ui) {
if ($(ui.draggable)[0].id != "") {
x = ui.helper.clone();
ui.helper.remove();
x.draggable({
helper: 'original',
containment: '#canvas',
snap: '.snap-target'
});
x.appendTo('#canvas');
}
}
});
});
I have created a jsfiddle:
https://jsfiddle.net/kuyn6gmc/
If you try and drag the blue box into the main canvas then release the mouse you will see how the box "pops" to the right slightly. When you move the box within the canvas, it works fine. On the fiddle it's not as bad as when it's full width on a browser, I think it's relative to the total width of the viewport.
If anyone knows why this may be happening I would appreciate it :)
Thank you
Michael

The reason this is occuring is because the draggable element is absolutely positioned relative to the viewport while it is being dragged. Once the element is appended, the positioning is relative to the #canvas element (because of position: relative), which is why the element moves when you drop it.
As the other answer suggests, you could remove position: relative from the element, however, that probably won't work in all cases. I'd suggest taking the positioning of the element into account before appending the element.
Updated Example
For instance, you could subtract the offset top/left positioning, as well as the width of the border. In doing so, the #canvas element can still be relatively positioned.
var canvasOffset = {
'top': parseInt($(this).offset().top, 10) + parseInt($(this).css('border-top-width'), 10),
'left': parseInt($(this).offset().left, 10) + parseInt($(this).css('border-left-width'), 10)
}
$draggble.css({
"top": parseInt($draggble.css('top'), 10) - canvasOffset.top + 'px',
"left": parseInt($draggble.css('left'), 10) - canvasOffset.left + 'px'
}).appendTo('#canvas');

You have to put position: relative to the body instead of the canvas.
.draggable { padding: 5px; float: left; margin: 0 10px 10px 0; font-size: .9em; position: relative; }
.small { border: 1px solid slateblue; width: 115px; height: 115px; background: #c5cae9 }
.ui-widget-header p, .ui-widget-content p { margin: 0; }
.text-box { text-align: center; vertical-align: middle; }
body { font-family: 'Helvetica Neue', Helvetica, Arial, serif; font-size: 13px }
#canvas { width: 600px; height: 300px; border: 1px solid #cccccc; margin: auto;
clear: both; }
.draggable-selectors { margin: 10px auto; width: 1000px; }
body { position: relative; margin: 0; }
<body class='snap-target'>

Related

How to put an element in hover state when scrolled down using javascript

I am trying to make a div element which when scrolled down will change properties drastically. Here is the codepen example of how I want it to work.
Instead of hover I want it so that when scrolled down, the page wide div will turn into that little circle div which when clicked will function as a back to the top button. It doesn't matter if more classes are added or anything of that sort. I am very new to js and I tried a few things and also googled about it, I got the scroll code from w3school's how to make a back to top button guide which specifies that when scrolled down by 20px the code would react, but I don't know how to turn the JavaScript to JS when scrolled down along with the transformation of the div.
Thanks in advance
I think you want to implement scroll to top functionality, very common these days in most of the web app.
You need to keep below things and design that feature.
There is one header, that should have a reference ID with hash to scroll back to top
Create a button that will always static position (JS) button, will show up when user scroll the window
Bind click event on the button that scroll back to top
Here is the you can see this implementation and use it.
.html
<h1 class="intro-copy">
Scroll down to use this simple back-to-top button made with modern vanilla javascript.
</h1>
<a class="top-link hide" href="" id="js-top">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6"><path d="M12 6H0l6-6z"/></svg>
<span class="screen-reader-text">Back to top</span>
</a>
.css
body {
height: 2000px;
position: relative;
}
.intro-copy {
padding: 1em;
margin: 50vh auto;
max-width: 15em;
font-family: Helvetica;
font-weight: lighter;
font-size: 2em;
line-height: 1.2;
text-align: center;
}
.top-link {
transition: all .25s ease-in-out;
position: fixed;
bottom: 0;
right: 0;
display: inline-flex;
cursor: pointer;
align-items: center;
justify-content: center;
margin: 0 3em 3em 0;
border-radius: 50%;
padding: .25em;
width: 80px;
height: 80px;
background-color: #F8F8F8;
&.show {
visibility: visible;
opacity: 1;
}
&.hide {
visibility: hidden;
opacity: 0;
}
svg {
fill: #000;
width: 24px;
height: 12px;
}
&:hover {
background-color: #E8E8E8;
svg {
fill: #000000;
}
}
}
// Text meant only for screen readers.
.screen-reader-text {
position: absolute;
clip-path: inset(50%);
margin: -1px;
border: 0;
padding: 0;
width: 1px;
height: 1px;
overflow: hidden;
word-wrap: normal !important;
clip: rect(1px, 1px, 1px, 1px);
&:focus {
display: block;
top: 5px;
left: 5px;
z-index: 100000; // Above WP toolbar
clip-path: none;
background-color: #eee;
padding: 15px 23px 14px;
width: auto;
height: auto;
text-decoration: none;
line-height: normal;
color: #444;
font-size: 1em;
clip: auto !important;
}
}
JS:
// Set a variable for our button element.
const scrollToTopButton = document.getElementById('js-top');
// Let's set up a function that shows our scroll-to-top button if we scroll beyond the height of the initial window.
const scrollFunc = () => {
// Get the current scroll value
let y = window.scrollY;
// If the scroll value is greater than the window height, let's add a class to the scroll-to-top button to show it!
if (y > 0) {
scrollToTopButton.className = "top-link show";
} else {
scrollToTopButton.className = "top-link hide";
}
};
window.addEventListener("scroll", scrollFunc);
const scrollToTop = () => {
// Let's set a variable for the number of pixels we are from the top of the document.
const c = document.documentElement.scrollTop || document.body.scrollTop;
// If that number is greater than 0, we'll scroll back to 0, or the top of the document.
// We'll also animate that scroll with requestAnimationFrame:
// https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
// ScrollTo takes an x and a y coordinate.
// Increase the '10' value to get a smoother/slower scroll!
window.scrollTo(0, c - c / 10);
}
};
// When the button is clicked, run our ScrolltoTop function above!
scrollToTopButton.onclick = function(e) {
e.preventDefault();
scrollToTop();
}

Tooltip moving with cursor

Image
ul#listcontainer .li1 {
display: block;
width: 210px;
height: 130px;
border: 1px solid red;
position: relative;
}
.li1 span {
position: absolute;
top: 140px;
left: 0px;
right: 0;
width: 220px;
padding: 2px 0;
background-color: #000;
background-color: rgba(0, 0, 0, 0.65);
color: #fff;
opacity: 0;
transition: opacity .5s ease-in-out;
text-align: center;
font-family: Arial;
font-size: 14px;
}
.li1:hover span {
opacity: 1;
}
.li1:hover span:hover {
opacity: 0;
}
<ul id="listcontainer">
<li class="li1">
<img src="images/li1.png"><span><b>Exteriors:</b> <br>Minimal Wear, Battle Scarred<br><br><img src="images/tick.png"><br> </span>
</li>
</ul>
Hello everyone. So I made a tooltip showing after I hover the box with red border. The thing I want is that when I hover over the div with red border - the tooltip begin to moving/following with the mouse. Tried to search how to do it but I didn't found answer. I think it will be some jQuery code... I let you guys tell me. Thanks.
Try this code and no need to change the css as shown in this http://jsfiddle.net/bo113jxu/8/ :
$('.li1').mousemove(function (e) {
$('span', this).css({left: e.pageX - 100, top: e.pageY + 10});
});
EDIT:
The position:absolute will work good as long as there's only one .li1 element, but in case we have more .li1 elements we'd face a problem shown in this jsfiddle demo1; TO fix this the position of .li1 should be set to fixed jsfiddle demo2.. just like what #ViktorMaksimov kudos said in his answer which I was wrong about it.
CSS code:
.li1 span {
position: fixed;
margin-left: -110px;
}
jQuery code:
$(document).ready(function() {
$('.li1').mousemove(function( event ) {
$(this).find('span').css({ //Position the tooltip
'left' : event.pageX + 'px', //Left position - the X position of the mouse
"top" : (event.pageY + 20) + 'px' //Top position - the Y position of the mouse
});
});
});
Firstly the tooltip should be positioned fixed.
When you are moving the mouse inside the <li> element the tooltip will have left position - the position on X of the mouse to the window, and top position the position on Y of the mouse + 20, because the tooltip not to be exactly next to the mouse, because if you move your mouse fast enough the tooltip will hide.
And we are setting margin-left to the tooltip - negative value half of its width to make the tooltip centered to the mouse.

Jquery height return false values

I'am serching solution in google. And saw some solutions to this but noone help me. When i asking in chrome about height(). It returns me true value, it's 1627. But when i write in script where it will be changed to this. It returns me 1290. And i don't know why. How can i return true height from document (because window can't help me). I'am trying with height(), innerHeight() and outerHeight().
Here is a screen with my problem: http://www.speedyshare.com/hTUDt/1.png
$(document).ready(function(){
var menu = $("#menu").height();
var content = $("body").outerHeight(true);
if(menu != content)
{
menu = content;
$("#menu").css({'height':menu+'px'});
}
});
or like this
$(document).ready(function () {
var menu = $('#menu');
$(window).resize(function () {
var height = $('#body').height();
menu.css({
'height': height + 'px',
});
}).trigger('resize');
});
It's doesn't work.
In css i have :
#menu {
width: 15%;
/*height: 100%;*/
background: #F5F5F5;
padding-top: 1%;
/* padding-bottom: 1%; */
font-size: 1.6rem;
font-family: 'Lato';
font-weight: 300;
color: #969696;
position: absolute;
border-right: 1px solid #c5c5c5;
box-shadow: 0px -1px 0px 1px #fff;
}
In firebug i see what's happend. He takes a height value 1290 (I don't know why) instead real height of body or 1626
$('element').css('height', 'auto !important')
Note: auto can be 100% or a fixed number (i.e '1626px')

jQuery - div Animation: on mouse over, the other divs change their position

I'm working on a jQuery animation that expands the height of a div.panel on mouse-in and contracts it back to normal on mouse-out.
The animation works for the selected div.panel, but the problem is relative at the nearby elements that moves down from their initial location when the mouse is over the div.panel.panel-big.
Here's a fiddle.
I presume you want the <li>s to expand, not the entire panel. The problem is that you're selecting .panel, which applies to the whole thing.
fiddle
JavaScript:
$(document).ready(function () {
$("li", this).hover(function () {
$(this).animate({
"height": "+=25px"
}, "fast");
}, function () {
$(this).animate({
"height": "-=25px"
}, 300);
});
});
Note the change from $(".panel", this).hover(…) to $("li", this).hover(…. This causes those pieces to properly expand/contract on mouse-in and mouse-out.
Tell me if this was not the intended behavior.
The problem is that in css, you have set the vertical align of the ".panel" to middle.
So when the ".panel-big" enlarges, the parent div (".row") also enlarges causing the panel-small to go down a little to remain centered vertically. Maybe you should set the vertical-align of the .panel to "top" and just put a margin-top for the panel-small.
.panel {
color: #ffffff;
margin: 10px 5px;
text-align: center;
font-size: 13pt;
vertical-align: top;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
display: inline-block;
}
.panel-small {
background-color: #bfbfbf;
width: 250px;
height: 450px;
max-height: 475px;
margin-top: 50px;
}
Here is your fiddle which i tweaked:
http://jsfiddle.net/2zgXC/4/

Large background images causing lag while scrolling

The website I am building has 4 large background images that take up the entire height and width of the user's browser. They are implemented as CSS background divs. The problem is, when scrolling on larger screen sizes, it is very laggy and choppy. Scrolling between these images is done automatically via JavaScript when the user presses a button, so this is part of the core functionality of my website and I must find a way to prevent lag.
So far, I have tried preloading the images via JS and converting the images from PNG to JPEG (increase compression and decrease quality) server-side. Neither of these worked.
The minimum height of the image can be 630 pixels. How can I prevent lag while scrolling between sections?
Here's my code:
CSS:
body { height: 100%; margin: 0px; font-family: HelveticaNeue, Helvetica, Arial, sans-serif; }
.area { height: 630px; border: 0px solid red; background: repeat-x; margin-bottom: 0px; }
a { text-decoration: none; }
h1, h2, h3, h4, h5, h6 { font-family: Av, Helvetica, Arial, sans-serif; color: #292E37; font-weight: lighter; }
#top { position: fixed; width: 100%; height: 10%; background: #292E37; box-shadow: inset 0px -1px 5px #000; z-index: 1000; }
#navigation { float: right; height: 100%; }
#bottom { width: 100%; position: fixed; bottom: 0px; padding: 10px; background: #292E37; box-shadow: inset 0px 1px 5px #000; text-shadow: 0px 1px 0px #000; color: #fff; }
#sceneSelection { top: 20%; position: fixed; padding: 10px; }
#info { margin-top: 50px; margin-bottom: 50px; }
.box { margin-top: 50px; padding: 75px; background: #292E37; box-shadow: inset 0px 1px 5px #000; text-shadow: 0px 1px 0px #000; color: #fff; }
.nav { position: relative; top: 38%; height: 100%; margin-right: 35px; display: inline-block; color: #fff; text-shadow: 0px 1px #000; }
.nav:hover { color: #EA5555; }
.nimage { float: left; width: 16px; height: 16px; position: relative; top: 5%; left: -20%; }
.home { background: url(site_images/icons/nav/home.png); }
.pricing { background: url(site_images/icons/nav/pricing.png); }
.features { background: url(site_images/icons/nav/features.png); }
.blog { background: url(site_images/icons/nav/blog.png); }
.contact { background: url(site_images/icons/nav/contact.png); }
.about { background: url(site_images/icons/nav/us.png); }
.logo { font-size: 2em; text-shadow: 0px 1px #000; padding-top: 10px; padding-left: 15px; color: #EA5555; font-family: Av, Helvetica, Arial, sans-serif; }
.red { color: #EA5555; }
.white { color: #fff; text-shadow: 0px 1px 0px #000; font-weight: bold; }
.dark { color: #202020; }
.center { text-align: center; }
.left { text-align: left; }
.right { text-align: right; }
.larger { font-size: 1.25em; }
.buttoni { -webkit-border-radius: 2px; -moz-border-radius: 0px; border-radius: 4px; background: #ddd; display: block; color: #ccc; font-size: 14pt; height: 50px; text-align: right; margin: 10px; cursor: pointer; color: #505050; }
.buttoni:hover { background: #EA5555; color: #fff; }
.btext { padding: 15px; position: relative; top: 25%; }
.groundi { background: url(ground_button.png); }
.skyi { background: url(sky_button.png); }
.stratospherei { background: url(stratosphere_button.png); }
.spacei { background: url(space_button.png); }
.image { height: 50px; width: 50px; float: left; border-top-left-radius: 5px; border-bottom-left-radius: 5px; }
li { color: #EA5555; }
li span { color: #505050; }
HTML:
<div class="space area" id="a4">
</div>
<div class="stratosphere area" id="a3">
</div>
<div class="sky area" id="a2">
</div>
<div class="ground area" id="a1">
</div>
JavaScript:
function scroll_to(id, speed, margin) {
$('html, body').animate({
scrollTop: $('#' + id).offset().top - margin
}, speed);
}
function match_height() {
var heights = [11, 630, 693, 756, 819, 882, 945, 1008, 1071, 1134, 1197, 1260, 1323, 1386, 1449, 1512, 1575, 1638, 1701, 1764, 1827, 1890, 1953, 2016, 2079, 2142, 2205, 2268, 2331, 2394, 2457, 2520];
var browsery = $(window).height();
var i = 0;
while(browsery > heights[i]) {
i++;
}
var h = heights[i];
$(".area").css("height", h + "px");
$(".area").css("width", "100%");
$(".ground").css("background", "url(scenes/ground/" + h + ".png)");
$(".sky").css("background", "url(scenes/sky/" + h + ".png)");
$(".stratosphere").css("background", "url(scenes/stratosphere/" + h + ".png)");
$(".space").css("background", "url(scenes/space/" + h + ".png)");
}
match_height();
var pos = 0;
$(".buttoni").click(function() {
var id = $(this).attr("id");
if(pos != id) {
scroll_to("a" + id, 2000, 0);
}
pos = id;
});
OP,
For browsers that support 3d transforms, e.g.: -webkit-transform, you could try the following:
your.div { -webkit-transform: translate3d(0,0,1px); }
Might not look like much, but doing the above causes the div in question to be hardware-accelerated.
Should you run into any flickering issues—they've been known to turn up in some cases—the following should sort you out:
your.div {
-webkit-transform: translate3d(0,0,1px);
-webkit-backface-visibility: hidden;
}
Via David Walsh - http://davidwalsh.name/translate3d
The use of translate3d pushes CSS animations into hardware acceleration. Even if you're looking to do a basic 2d translation, use translate3d for more power! If your animation is still flickering after switching to the transform above, you can use a few little-known CSS properties to try to fix the problem
Hope that helps.
As per my understanding, the issue and the solution drafted in the OP is two-fold:
initially, within the match_height() function, the OP author retrieves the images that best fits the screen height, so that upon completed animation the user sees one full background image.
after initial load, the user can navigate up and down the sections (with their respective background images) with the help of some buttons that trigger the scroll_to() function and its contained animation. Here is where the actual problem resides.
My efforts and the resulting fiddle focus on the scroll_to() function and the associated animation. I applied the following measures that, in conjunction, result in a (as per my subjective observation) 'smoother' scolling experience:
the original animation happened against 'html' and 'body', I'm reducing the jQuery selector to one selector only. In order to be able to use jQuery 1.9 (where jQuery.browser is deprecated) I'm using feature detection to get the 'right' selector:
function getScrollerSelector() {
var $body = $("<body/>");
$body.scrollTop(1);
return $body.scrollTop() == 1 ? "body" : "html";
}
In order to reduce the browser's processing load, I'm applying a logic that, per CSS, sets the background image of invisible sections to none during scrolling:
.scrolldown.scrollto-a2 #a1,
.scrolldown.scrollto-a3 #a1, .scrolldown.scrollto-a3 #a2,
.scrolldown.scrollfrom-a3 #a4,
.scrolldown.scrollfrom-a2 #a4, .scrolldown.scrollfrom-a2 #a3,
.scrollup.scrollto-a3 #a4,
.scrollup.scrollto-a2 #a4, .scrollup.scrollto-a2 #a3,
.scrollup.scrollfrom-a2 #a1,
.scrollup.scrollfrom-a3 #a1, .scrollup.scrollfrom-a3 #a2
{ background: none; }
I played around with linear easing, but that did not necessarily improve anything
All in all, scrolling doesn't seem choppy to me any more, but please take into account that this is also dependent on the client computers processing power.
Here's the scroll_to() function:
function scroll_to(id, speed, margin) {
var currentScrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
var scrollTop = $('#' + id).offset().top - margin;
var direction = scrollTop > currentScrollTop ? "down" : "up";
$("body").addClass("scroll"+direction + " scrollto-"+id + " scrollfrom-"+getScrollFrom(direction));
$( scrollerSelector ).animate({
scrollTop: scrollTop
}, {
//easing: 'linear',
duration: speed,
complete: function() {
$("body").removeClass("scrollup scrolldown scrollto-a1 scrollto-a2 scrollto-a3 scrollto-a4 scrollfrom-a1 scrollfrom-a2 scrollfrom-a3 scrollfrom-a4");
}
}
);
}
This is the link to jsfiddle
Since you are Scaling up the image, you can tell the Browser how to handle the rendering of image.
During the animation / scrolling, you can tell browser to Optimize on Speed and on completion of Animation / scrolling, Optimize on Quality.
Here is the CSS Property you can use on img: 'image-rendering' with values as optimizeSpeed / optimizeQuality.
https://developer.mozilla.org/en-US/docs/CSS/image-rendering
One thing you could do to images is smush it using http://www.smushit.com/ysmush.it/
this reduces the size of the image without loosing quality removing all unwanted meta data.
Testing locally it seems like your code should work ok, I have firefox 15 and chrome and don't see any lagging
What if you try this for the scroll to method?
function scroll_to(id, speed, margin) {
$('html, body').animate({
scrollTop: $('#' + id)
}, speed);
}
I had a similar problem with a website I was working on. In the end the problem seemed to be because of the large dimensions of the image that the computer/browser had to compute and render on screen.
My recommendation would be to try and reduce the amount of image that needs to be shown and scrolled on screen if possible.
Most modern browsers now support hardware (graphics card) rendering instead of the traditional (usually slower) software based (CPU) rendering. Hardware based rendering should in theory reduce that lag you're experiencing. However if your PC only has base or average graphics rendering capabilities, you're not going to have much success regardless. I personally had no success with either in Chrome, FireFox or IE until I gave in and removed the images.

Categories

Resources