I'm encountering a strange bug in chrome (also happen in chromium) but not under firefox.
I'm coding something to be able to resize some divs.
Sometimes in chrome a sibling div is displaying as 0px height when I'm resizing. For example, in this fiddle, if you drag the resizing line between the red and the blue div, the green div disappear.
I put a breakpoint on the code of the mousemove handler in order to inspect the div, but the css is exactly the same as the div displaying correctly.
To try it put a breakpoint here :
$("*").mouseup(function(event) {
if (downV) {
downV = false;
Is this a webkit related bug or am I doing something wrong? How can I fix this?
The problem seems to be, that it – for whatever reason – doesn't like the mixed units (percent and pixel values) while moving. Check out this fiddle, I've changed the code in $(".area").mousemove(function(event) to use percent values and commented out the conversion px => % in the $("*").mouseup(function(event) method and it seems to works correctly:
mouseup:
$("*").mouseup(function(event) {
if (downV) {
downV = false;
$("body").css("cursor","initial");
//upchild.css("height", upchild.height()*100/sizeTot+"%");
//downchild.css("height", downchild.height()*100/sizeTot+"%");
event.stopPropagation();
} else if (downH) {
downH = false;
$("body").css("cursor","initial");
upchild.css("width", upchild.width()*100/sizeTot+"%");
downchild.css("width", downchild.width()*100/sizeTot+"%");
event.stopPropagation();
}
});
mousemove:
$(".area").mousemove(function(event) {
if (downV){
var y = event.pageY - $(this).offset().top - upperSize;
if (y < 0) {
y = 0;
}
if (y > sizePart) {
y = sizePart;
}
upchild.css("height", (Math.floor(y)+1)*100/sizeTot+"%");
downchild.css("height", Math.floor(sizePart-y)*100/sizeTot+"%");
event.preventDefault();
} else if (downH) {
var x = event.pageX - $(this).offset().left - upperSize;
if (x < 0) {
x = 0;
}
if (x > sizePart) {
x = sizePart;
}
upchild.css("width", Math.floor(x)+1);
downchild.css("width", Math.floor(sizePart-x));
event.preventDefault();
}
});
Related
I created a site which is devided vertically into two columns (each one half of the screen). If I scroll down, having the cursor on any position on the site, the left column should behave normal and scroll down, at the same the right column should scroll up in the opposite direction.
I came along this question – Modify scroll direction – and tried to get a solution out of it, but I cant get it working.
This is what I tried: http://jsbin.com/UJEBohu/1/edit
I've made a working solution, here: http://jsfiddle.net/QDUyR/1/
Put this in your <body> onload event and you should be set :)
// Add event listener for scrolling
$("#left").on("scroll", function () {
var scrolledleft = parseInt($("#left").scrollTop()) * -1;
console.log(scrolledleft + scrolledright)
$("#right").scrollTop(scrolledleft + scrolledright)
})
//Move right column to bottom initially
$("#right").scrollTop($("#right").height())
//Get actual distance scrolled
var scrolledright = parseInt($("#right").scrollTop())
Edit: Updated to work no matter what height the div's have, as long as they are equal.
The different browsers all scroll a different amount each time you scroll.
Here's my updated fiddle i have not tried it yet in safari.
I'm using a bind on the mouse wheel because Mozilla's scroll event fires multiple times every time you scroll once.
First I check to see which browser we are using and setting how much each scroll will be for that browser. Then I calculate how much to move the right div based on the amount to scroll for each browser.
In the mouse wheel event I check to make sure the right div does not go to far below or above the screen.
I'm using event.originalEvent.detail to tell which direction the mouse wheel is going in mozilla, and in IE and Chrome I am using event.originalEvent.wheelDelta.
Below is the code.
$(function()
{
if (navigator.userAgent.indexOf('Firefox') != -1 && parseFloat(navigator.userAgent.substring(navigator.userAgent.indexOf('Firefox') + 8)) >= 3.6)
{
//Firefox
var eachScroll = 114;
}
else if (navigator.userAgent.indexOf('Chrome') != -1 && parseFloat(navigator.userAgent.substring(navigator.userAgent.indexOf('Chrome') + 7).split(' ')[0]) >= 15)
{
//Chrome
var eachScroll = 100;
}
else if(navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Version') != -1 && parseFloat(navigator.userAgent.substring(navigator.userAgent.indexOf('Version') + 8).split(' ')[0]) >= 5)
{
//Safari
}
else
{
//IE
var eachScroll = 94;
}
var windowHeight = $(window).height();
var containerHeight = $("#container").height();
var heightLeftover = containerHeight - windowHeight; // Actual amount left to scroll
var totalScrolls = heightLeftover / eachScroll; // Total number of scrolls
totalScrolls = Math.ceil(totalScrolls); // Always round up
var amountToScroll = ($("#right").height() - containerHeight) / totalScrolls;
// Amount that right div will move every time we scroll
$(window).bind("mousewheel DOMMouseScroll", function(event){
var top = $("#right").position().top;
if(event.originalEvent.wheelDelta) // Check if wheelDelta exists
{
if(event.originalEvent.wheelDelta == - 120)
{
if(top < 2)
$("#right").css({top: top + amountToScroll});
}
else
{
if(top > -2000)
$("#right").css({top: top - amountToScroll});
}
}
else if(event.originalEvent.detail) // check if detail exists
{
if(event.originalEvent.detail == 3)
{
if(top < 2)
$("#right").css({top: top + amountToScroll});
}
else
{
if(top > -2000)
$("#right").css({top: top - amountToScroll});
}
}
});
});
I have developed a Windows application using TideSDK with HTML , CSS and Javascript.To give it a widget look I disappered its title bar.So I can't drag it.The TideSDK documentation says "after disappearing title bars, you can drag window using its contents with javascript".
How can I drag the window with javascript selecting its components(tiles in my case)?Any tutorial or code as I found nothing on google with my search.
My App looks like below:
I've written the following generic function for dragging using JS:
function setDragOfElementOnAnother ($draggableElement, $draggedElememnt, allowDragPredicate) {
var stopDragFunction = function() {
$draggedElememnt.data("drag", false);
$draggedElememnt.removeData("startPoint");
$("html, body").unbind("mouseup.drag");
$("html, body").unbind("mousemove.drag");
};
var dragFunction = function(e) {
if (!parseBoolean($draggedElememnt.data("drag")))
return;
var begin = $draggedElememnt.data("startPoint");
$draggedElememnt.css({ left: e.clientX - begin.x, top: e.clientY - begin.y });
};
$draggableElement.mousedown(function(e) {
if ((e.clientX - $(this).offset().left < 0 || $(this).offset().left + $(this).width() < e.clientX) ||
e.clientY - $(this).offset().top < 0)
return;
if (allowDragPredicate && !allowDragPredicate(e))
return;
$draggedElememnt.data("drag", true);
$draggedElememnt.data("startPoint", Point(e.clientX - $(this).offset().left, e.clientY - $(this).offset().top));
$("html, body").bind("mouseup.drag", stopDragFunction);
$("html, body").bind("mousemove.drag", dragFunction);
});
$draggableElement.mouseup(stopDragFunction);
$draggableElement.mousemove(dragFunction);
}
This function is used to declare dragging of one element using another.
Prerequisites:
(1) The dragged element's position has to be either fixed or absolute (relative should also work). (2) jQuery.
By specifying both dragged and draggable elements as the same one, pressing on the element and moving the mouse will cause the element to drag.
The 'allowDragPredicate' variable is optional, and is useful to create boundaries.
EDIT: Forgot. Also add the code:
function Point(xVal, yVal) {
if (xVal === undefined) {
xVal = 0;
}
if (yVal === undefined) {
yVal = 0;
}
return {
x: xVal,
y: yVal
};
}
EDIT 2: And:
function parseBoolean(str) {
if (str === true)
return true;
if (str)
return /^true$/i.test(str);
return false;
}
EDIT 3: And, added a simple jsFiddle example.
I have created a parallax scroll, which seem to be working fine in firefox however in the chrome browser there's a slight jump on the body text when scrolling. click here scroll to the about section. I am not sure if t this is a css or JS issue.. below is a snippet i have incorporated into my parallax function
Does anyone know how i an fix this issue?
$(document).ready(function(){
// Cache the Window object
$window = $(window);
// Cache the Y offset and the speed of each sprite
$('[data-type]').each(function() {
$(this).data('offsetY', parseInt($(this).attr('data-offsetY')));
$(this).data('Xposition', $(this).attr('data-Xposition'));
$(this).data('speed', $(this).attr('data-speed'));
});
// For each element that has a data-type attribute
$('[data-type="background"]').each(function(){
// Store some variables based on where we are
var $self = $(this),
offsetCoords = $self.offset(),
topOffset = offsetCoords.top;
// When the window is scrolled...
$(window).scroll(function() {
// If this section is in view
if ( ($window.scrollTop() + $window.height()) > (topOffset) &&
( (topOffset + $self.height()) > $window.scrollTop() ) ) {
// Scroll the background at var speed
// the yPos is a negative value because we're scrolling it UP!
var yPos = -($window.scrollTop() / $self.data('speed'));
// If this element has a Y offset then add it on
if ($self.data('offsetY')) {
yPos += $self.data('offsetY');
}
// Put together our final background position
var coords = '50% '+ yPos + 'px';
// Move the background
$self.css({ backgroundPosition: coords });
$('[data-type="scroll-text"]', $self).each(function() {
var $text= $(this);
var pos = ($window.scrollTop()/10) * $text.data('speed');
var curP = $text.css('margin-top');
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
if(is_chrome) {
$text.animate({
paddingTop: pos,
}, 200, 'linear', function() {
// Animation complete.
});
} else {
$text.css('padding-top', pos);
}
});
}; // in view
}); // window scroll
}); // each data-type
}); // document ready
Some suggestions:
1.) Use position: fixed to avoid any jitter, as you'll be taking the element out of the document flow. You can then position it using z-index.
2.) Cache as much as you can to ease processing time.
3.) Math.round may not be necessary, but try adding this CSS to your moving areas: -webkit-transform: translate3d(0,0,0); This will force hardware acceleration in Chrome, which may ease some of the jittering. (It looked smoother on my screen when I added this with Inspector, but it didn't get rid of the jumpiness with the scroll wheel.) Note: Don't do this on your entire document (e.g. body tag), as it might cause some issues with your current layout. (Your navigation bar didn't stick to the top of the window, for instance.)
4.) If you have any animations running as part of your parallax logic (tweening the margin into place or something along those lines), remove it - that would probably cause the jump you see.
Hope this helps. Best of luck.
I see the same jittering in FireFox and Chrome (Mac). Looking at your containers, one thing that's glaring at me is the pixel position that's being calculated/used.
Chrome: <div id="about-title" style="margin-top: 1562.3999999999999px;">
FireFox: <div id="about-title" style="margin-top: 1562.4px;">
Browsers aren't going to allow content to sit at 1/2 pixel, let alone 0.3999999 of a pixel. I think it's moving it, and trying to calculate whether to round up or round down. It jitters because it's calculating with every click of your mouse wheel.
Thus, I'd try adding Math.round() to your positions so that the containers are never being left in limbo.
Take a look at the code here: http://webdesigntutsplus.s3.amazonaws.com/tuts/338_parallax/src/index.html
Firebug some of the elements, and you'll see that their only fraction of a pixel is '0.5'. Most of them (the bulk) go to round number values.
You are going to have to change the way that the scrolling works (i.e. change how the spacing is computed), but this can be fixed by adding the position:fixed CSS element to the page elements that are scrolling. The problem is coming from the time that it takes for the JavaScript to process and then render.
For example, on your page you would set each of the <div> tags containing text to have a fixed position and then use the JavaScript/JQuery function to update the top: CSS element. This should make the page scroll smoothly.
Have you tried adding the preventdefault inside the scroll function?
$(window).scroll(function(e) {
e.preventDefault();
// rest of your code
}
In a previous question I created a fairly good parallax scrolling implementation. Jquery Parallax Scrolling effect - Multi directional You might find it useful.
Here's the JSFiddle http://jsfiddle.net/9R4hZ/40/ use the up/down arrows or scroll wheel.
Using padding and margin for the positioning are probably why you're experiencing rendering issues. While my code uses scroll or keyboard input for the effect you can loop the relavent portion and check the $moving variable until you reach the desired element on screen.
function parallaxScroll(scroll) {
// current moving object
var ml = $moving.position().left;
var mt = $moving.position().top;
var mw = $moving.width();
var mh = $moving.height();
// calc velocity
var fromTop = false;
var fromBottom = false;
var fromLeft = false;
var fromRight = false;
var vLeft = 0;
var vTop = 0;
if($moving.hasClass('from-top')) {
vTop = scroll;
fromTop = true;
} else if($moving.hasClass('from-bottom')) {
vTop = -scroll;
fromBottom = true;
} else if($moving.hasClass('from-left')) {
vLeft = scroll;
fromLeft = true;
} else if($moving.hasClass('from-right')) {
vLeft = -scroll;
fromRight = true;
}
// calc new position
var newLeft = ml + vLeft;
var newTop = mt + vTop;
// check bounds
var finished = false;
if(fromTop && (newTop > t || newTop + mh < t)) {
finished = true;
newTop = (scroll > 0 ? t : t - mh);
} else if(fromBottom && (newTop < t || newTop > h)) {
finished = true;
newTop = (scroll > 0 ? t : t + h);
} else if(fromLeft && (newLeft > l || newLeft + mw < l)) {
finished = true;
newLeft = (scroll > 0 ? l : l - mw);
} else if(fromRight && (newLeft < l || newLeft > w)) {
finished = true;
newLeft = (scroll > 0 ? l : l + w);
}
// set new position
$moving.css('left', newLeft);
$moving.css('top', newTop);
// if finished change moving object
if(finished) {
// get the next moving
if(scroll > 0) {
$moving = $moving.next('.parallax');
if($moving.length == 0)
$moving = $view.find('.parallax:last');
} else {
$moving = $moving.prev('.parallax');
if($moving.length == 0)
$moving = $view.find('.parallax:first');
}
}
// for debug
$('#direction').text(scroll + " " + l + "/" + t + " " + ml + "/" + mt + " " + finished + " " + $moving.text());
}
May not be related to your specifics, but I had a jumpy parallax scrolling problem, I was able to solve it adding the following CSS for the fixed portions of the page:
#supports (background-attachment: fixed)
{
.fixed-background
{
background-attachment: fixed;
}
}
Not sure of all the specifics, but found at Alternate Fixed & Scroll Backgrounds
Does that title sound confusing? I thought it might well anyways.
When I person clicks on the page I want them to be able to me a little line shorter and long.
You can see what I mean here:
http://jsfiddle.net/shawn31313/HKLhE/9/show/
Do a Mousedown and them move your move to the right. It works fine.
But now, move you mouse to the left. See the problem? It goes the same direction as it did when you dragged to the right. I know this is because i'm using width and obviously width on goes one way.
This is my code so far:
$(document).ready(function() {
var dragStatus = 0,
getPos, giveRandomID;
$(document).mousedown(function(event) {
dragStatus = 0;
getPos = {
top: event.clientY,
left: event.clientX
};
giveRandomID = Math.floor(Math.random() * 99999);
});
$(document).mousemove(function() {
var line = $('#line' + giveRandomID);
if (dragStatus == 0) {
$('body').append("<div id='line" + giveRandomID + "' class='line' style='position:absolute;top:" + getPos.top + "px;left:" + getPos.left + "px;background:black;width:2px;height:5px'></div>");
dragStatus = 1;
}
if (dragStatus == 1) {
if (event.clientX > line.offset().left) {
line.css({
width: event.clientX - line.offset().left
});
} else {
line.css({
width: line.offset().left - event.clientX
});
}
//for DEG "-" Top-Math.abs(DEG*2) for Deg "+" Top+(DEG*2)
}
});
$(document).mouseup(function() {
dragStatus = 2;
});
});
I hope someone can help me out with this. Maybe a complete different way to set this up. Just something to fix this issue
To make the line stretch to the left, you have to update the left property:
if (event.clientX > getPos.left) {
line.css({
left: getPos.left,
width: event.clientX - getPos.left
});
} else {
line.css({
left: event.clientX,
width: getPos.left - event.clientX
});
}
jsFiddle: http://jsfiddle.net/HKLhE/16/
You'll need to modify the else case (moving right) to set the left property to auto and the right property to the initial mouse click X position. Comparing to the offset().left when moving left won't work because that value is changing.
Try this out for size:
http://jsfiddle.net/HKLhE/20/
Edit: Brilliand's solution is much more elegant.
I have a function to follow the object after the mouse,
and I want to be able to stop and start following at will, without hiding the object.
It almost works as I wanted, and is following the mouse indeed, but I cannot make it move initial position without actually moving the mouse.
E.G. When I trigger the function, the object is still somewhere in another place, until I move the mouse, but what I'm trying to do is to move it the initial position first, before attaching the mousemove event.
Here is how I want to trigger the function:
showtrail();
function showtrail(shit){
//this is how I tried to set the initial position first, but this get me an error:..
//followmouse();
document.onmousemove=followmouse; //and this is how I attach the event.
}
This is a part of the actual function to move the object,
but, I can't get the coordinates if I try to initilize/imitate the first movement.
function followmouse(e){
var xcoord=offsetfrommouse[0]
var ycoord=offsetfrommouse[1]
if (typeof e != "undefined"){ //This- if triggered by mousemove, and it works
xcoord+=e.pageX
ycoord+=e.pageY
}
else { //this was meant for the initial call, but... for some reason
xcoord+=document.body.scrollLeft+event.clientX // it triggers an error,
ycoord+=document.body.scrollTop+event.clientY // saying event.clientX undefined.
}
}
So the event.clientX never seems to work, and I cannot figure out how to get the actual mouse position otherwise..
Please guide..
event.clientX and event.clientY are wrong. They should be e.clientX and e.clientY
A more elegant cross browser way to get xcoord and ycoord in followmouse(e) is:
xcoord = e.pageX||(e.clientX+(document.body.scrollLeft||document.documentElement.scrollLeft));
ycoord = e.pageY||(e.clientY+(document.body.scrollTop||document.documentElement.scrollTop));
Now if I'm getting it right, the object that follows is expected to have an initial absolute position and displayed as a block, meaning that you have initial x and y (left and top). Therefore by using a global bool var for currently following or not you're done.
<style>
...
#trail {position:absolute;left:0;top:0;display:none}
...
</style>
<script>
var following = false;
...
function followmouse(e){
if (!following){
document.getElementById('trail').style.display='none';
return;
}
...
document.getElementById('trail').style.display='block';
}
</script>
By changing display you have the option to move your #trail to its initial position and then follow the mouse, and the option to avoid the move and let it follow the mouse from its latest following position.
EDIT 1:
For this very purpose, I recommend using of requestAnimationFrame API, not classic DOM events. said API is more efficient for creating animations and pausing them.
take a look at this too: requestAnimationFrame for smart animating
This is sad, but true that you can not get mouse's initial position before moving mouse on a webpage. I mean you can't calibrate your object before mousemove event. this is what I will do in a similar project:
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<script type="text/javascript">
var targetID = 'mydiv'; // div that is to follow the mouse
var pauseFollowing = false;
// (must be position:absolute)
var offX = 15; // X offset from mouse position
var offY = 15; // Y offset from mouse position
function mouseX(evt) {if (!evt) evt = window.event; if (evt.pageX) return evt.pageX; else if (evt.clientX)return evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); else return 0;}
function mouseY(evt) {if (!evt) evt = window.event; if (evt.pageY) return evt.pageY; else if (evt.clientY)return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); else return 0;}
function follow(evt) {
if(pauseFollowing) {
//or do something else at pause
return false;
}
var obj = document.getElementById(targetID).style;
obj.visibility = 'visible';
obj.left = (parseInt(mouseX(evt))+offX) + 'px';
obj.top = (parseInt(mouseY(evt))+offY) + 'px';
}
function toggleFollow() {
pauseFollowing = !pauseFollowing;
}
window.onload = function() {
window.onclick = toggleFollow;
document.onmousemove = follow;
}
</script>
</head>
<body>
<div id="mydiv" style="visibility: hidden; top:0; left:0 ;width: 100px; height: 100px; background: #ff0; position: absolute;"></div>
</body>
</html>
Alright that's how I done it.
The best Idea was to always capture a move to set position in a global var.
Now I have an option to display it fixed at any specific place (if I pass coords to showtrail)
or to actually follow the mouse;
I also added an event listener, so if the mouse gets outside the window while following- it will be hidden.
So far it works exactly as I wanted:
var trailimage=["scripts/loading_mouse.gif", 24, 24] //image path, plus width and height
var offsetfrommouse=[2,10] //image x,y offsets from cursor position in pixels. Enter 0,0 for no offset
var global_coord=[0,0]
var follow=false;
if (document.getElementById || document.all)
document.write('<div id="trailimageid" style="z-index: 10;position:absolute;display:none;left:0px;top:0px;width:1px;height:1px"><img src="'+trailimage[0]+'" border="0" width="'+trailimage[1]+'px" height="'+trailimage[2]+'px"></div>')
function gettrailobj(){
if (document.getElementById)
return document.getElementById("trailimageid").style
else if (document.all)
return document.all.trailimagid.style
}
function hidett(){ gettrailobj().display="none"; }
function showtt(){ gettrailobj().display="block"; }
function truebody(){ return (document.body||document.documentElement); }
function showtrail(shit){
if (typeof shit == "undefined"){ //Follow Mouse
follow=true;
setmousepos(global_coord[0],global_coord[1]);
}
else { //Set fixed in specific place
follow=false;
showtt()
gettrailobj().left=shit.left+6+"px"
gettrailobj().top=shit.top-5+"px"
}
}
function hidetrail(){
hidett()
follow=false;
}
function setcoord(e){
var xcoord=offsetfrommouse[0]
var ycoord=offsetfrommouse[1]
var xxcoord = e.pageX||(e.clientX+truebody().scrollLeft);
var yycoord = e.pageY||(e.clientY+truebody().scrollTop);
if (typeof xxcoord != "undefined"&&typeof yycoord != "undefined"){
xcoord+=xxcoord;
ycoord+=yycoord;
global_coord=[xcoord,ycoord];
if (follow) setmousepos(xcoord,ycoord);
}}
function setmousepos(xcoord,ycoord){
var docwidth=truebody().scrollLeft+truebody().clientWidth
var docheight=Math.max(truebody().scrollHeight, truebody().clientHeight)
if ((xcoord+trailimage[1]+3>docwidth || ycoord+trailimage[2]> docheight ||!follow)){
hidett()
}
else{
showtt();
gettrailobj().left=xcoord+"px"
gettrailobj().top=ycoord+"px"
}
}
window.addEventListener("mouseout",
function(e){
mouseX = e.pageX;
mouseY = e.pageY;
if ((mouseY >= 0 && mouseY <= window.innerHeight)
&& (mouseX >= 0 && mouseX <= window.innerWidth)){
return false;
}else{
if (follow) hidett()
}
},
false);
document.onmousemove=setcoord;