Floating nav bar that stops fixed to the top of the page - javascript

I am trying to mimic something that I have seen a few different times. There is usually a banner with a nav bar below and when the page is scrolled it moves until it touches the top then stops and stays fixed. I am not completely sure how to accomplish this. I have seen a few different things that just dont work.
After looking around I figured out it will work something like this but I can seem to get it to work. I think I am missing some stuff
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
<!--
#Table_01 {
position:relative;
left:0px;
top:0px;
width:1020px;
height:854px;
text-align: left;
margin-right: auto;
margin-left: auto;
}
body {
font-family: Verdana, Geneva, sans-serif;
font-size: 12px;
color: #a4c639;
text-align: center;
margin: 0px;
}
-->
</style>
<script type='text/javascript'>
var topPos = 120;
var updatedPos;
window.onscroll = navPos;
if (!topPos) {
topPos = 120;
}
function navPos() {
var pos = window.scrollY;
if (!topPos) {
topPos = 120;
}
var st = document.getElementById('navTest');
if (st) {
if (pos < topPos && updatedPos != 'absolute') {
st.style.position = 'absolute';
st.style.top = topPos + 'px';
updatedPos = 'absolute';
//alert('Switched to absolute');
} else if (pos >= topPos && updatedPos != 'fixed') {
st.style.position = 'fixed';
st.style.top = '0';
updatedPos = 'fixed';
//alert('Switched to fixed');
}
}
}
navPos();
</script>
</head>
<body>
<div id="Table_01">
<div id='navTest' style='position:absolute;z-index:999;top:120px;left:0; height:50px;width:100%; background-color:#000;' width='100%'>
</div>
</div>
</body>
</html>

All references to a non-existant navTopPos variable should be changed to reference the topPos variable. Your JS code should now be:
var topPos;
var updatedPos;
window.onscroll = navPos;
if (!topPos) {
topPos = 120;
}
function navPos() {
var pos = window.scrollY;
if (!topPos) {//this line was changed
topPos = 120;//this line was changed
}
var st = document.getElementById('navTest');
if (st) {
if (pos < topPos && updatedPos != 'absolute') {
st.style.position = 'absolute';
st.style.top = topPos + 'px';//this line was changed
updatedPos = 'absolute';
//alert('Switched to absolute');
} else if (pos >= topPos && updatedPos != 'fixed') {
st.style.position = 'fixed';
st.style.top = '0';
updatedPos = 'fixed';
//alert('Switched to fixed');
}
}
}
navPos();
The interpreter died somewhere here:
if (!topNavPos) {
topNavPos = 120;
}
​
Updated JSFiddle with the necessary changes.

Related

how to move element with arrow using Javascript

I'm still learning JS and I'm trying to move this div with arrows using Javascript but it moves only 1 step per click can someone please help me how to make it moves more steps
check my code please
let
div = document.getElementById("test");
function move(e){
if(e.keyCode ==40){
div.style.top = 10+"px"
}
if(e.keyCode ==38){
div.style.top = -10+"px" }
if(e.keyCode==39){
div.style.left = 10 +"px"
}
if(e.keyCode==37){
div.style.left = -10 +"px"
}
}
window.onkeydown = move;
div{
width: 200px;
height: 200px;
background-color: red;
position: absolute;
}
<!DOCTYPE html>
<html>
<head>
<title>index</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="test"></div>
<script src="test.js"></script>
</body>
</html>
Try this code, you need the current position
I use getBoundingClientRect
You might also look at code instead of keyCode
const div = document.getElementById("test");
function move(e) {
const pos = div.getBoundingClientRect()
let top = pos.top;
let left = pos.left;
const code = e.code;
switch (code) {
case "ArrowRight": left += 10; break;
case "ArrowLeft" : left -= 10; break;
case "ArrowUp" : top -= 10; break;
case "ArrowDown" : top += 10; break;
}
div.style.top = `${top}px`;
div.style.left = `${left}px`;
}
window.addEventListener("keydown",move);
div {
width: 200px;
height: 200px;
background-color: red;
position: absolute;
}
<div id="test"></div>
You can save the current position then move it again, set an offset and add/remove distance at every keydown
const div = document.getElementById("test");
let position = 0
const offset = 10;
function move(e) {
if (e.keyCode == 40) {
position += offset;
div.style.top = position + "px"
}
if (e.keyCode == 38) {
position -= offset;
div.style.top = position + "px"
}
if (e.keyCode == 39) {
position += offset;
div.style.left = position + "px"
}
if (e.keyCode == 37) {
position -= offset;
div.style.left = position + "px"
}
}
document.onkeydown = move;
div {
width: 200px;
height: 200px;
background-color: red;
position: absolute;
}
<!DOCTYPE html>
<html>
<head>
<title>index</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="test"></div>
<script src="test.js"></script>
</body>
</html>
You are setting its offset to a fixed value of 10 or -10.
You need to store the current position somehow and offset the new position based on the current one.
//Intiate once at the beginning of the script
let currentVerticalPosition = 0;
if(e.keyCode ==40){
currentVerticalPosition += 10;
div.style.top = currentVerticalPosition +"px";
}

Colliding two circles without using canvas

I have created three circles and made it bounce off the wall without using HTML canvas. Now I want two circles to collide with each other and move those circles in the opposite direction. I tried to detect the collision by checking it's position but it doesn't work. I don't know where I went wrong.
Here's my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Bounce Ball</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.circle{
height: 50px;
width: 50px;
position: absolute;
border-radius: 50%;
}
.container {
height: 300px;
width: 300px;
background-color: skyblue;
position: relative;
}
</style>
</head>
<body>
<div class ="container" id ="container">
<div class="circle" id = "circle1" style="background-color:black;
height: 50px; width: 50px;top:0; left:0"></div>
<div class="circle" id ="circle2" style="background-color:rgb(197, 100,
100);height: 50px; width: 50px;top:200px;left: 150px"></div>
<div class="circle" id ="circle3" style="background-color:brown;height:
50px;width: 50px;top:50px;left: 640px"></div>
</div>
<script>
var container = document.getElementById("container");
container.style.width="700px";
container.style.height = "300px";
var balls = document.getElementsByClassName("circle");
for(var i=0; i <balls.length; i++){
var speed={x:3,y:-3}
setInterval(draw, 50 , balls[i], speed);
}
function draw(ball, speed) {
if(parseInt(ball.style.left) > (parseInt(container.style.width)-
parseInt(ball.style.width)) || (parseInt(ball.style.left) <0) ){
speed.x = -speed.x;
}
ball.style.left = parseInt(ball.style.left) + speed.x + 'px';
if(parseInt(ball.style.top) > (parseInt(container.style.height)-
parseInt(ball.style.height)) || (parseInt(ball.style.top) <0)){
speed.y = -speed.y;
}
ball.style.top = parseInt(ball.style.top) + speed.y + 'px';
//for colliding two circles
for(var i =0 ; i <= balls.length-1; i++){
for(var j = i + 1; j < balls.length; j++){
if(parseInt(balls[i].style.left) +
parseInt(balls[i].style.width) ==
parseInt(balls[j].style.left) ||
parseInt(balls[j].style.left) +
parseInt(balls[j].style.width) ==
parseInt(balls[i].style.left) &&
parseInt(balls[i].style.top) +
parseInt(balls[i].style.height) ==
parseInt(balls[j].style.top) || parseInt(balls[j].style.top)
+ parseInt(balls[j].style.height) ==
parseInt(balls[i].style.top)) {
speed.x = - speed.x;
speed.y = -speed.y;
}
ball[i].style.left = parseInt(ball[i].style.left) +
speed.x + 'px';
ball[j].style.left = parseInt(ball[j].style.left) +
speed.x + 'px';
ball[i].style.top = parseInt(ball[i].style.top) +
speed.y + 'px';
ball[j].style.top = parseInt(ball[j].style.top) +
speed.y + 'px';
}
}
}
</script>
</body>
</html>
I would recommend moving as much as possible into javascript variables so you don't need to consult the HTML for every parameter.
You had quite the number of typos, among them speed.x = - speed.x; where you meant speed.x = -speed.x; and your code was difficult to read without any comments or helper functions to explain what's going on.
I have fixed your typos and restructured your code in the snippet below. Try checking the developer console, typically by pressing F12, as this will show you code errors with line number and severity rating.
In my snippet below i have tried to move the parameters into JavaScript to show how that would work, while still leaving some on the HTML nodes:
//Basic properties
var width = 700;
var height = 300;
//Get container
var container = document.getElementById("container");
// Set dimensions
container.style.width = width + "px";
container.style.height = height + "px";
//Load balls
var balls = Array.prototype.slice.call(document.getElementsByClassName("circle"))
.map(function(ball) {
return {
HTMLNode: ball,
xPos: parseInt(ball.style.left),
yPos: parseInt(ball.style.top),
xAcc: 3,
yAcc: -3,
size: 50
};
});
//Utility functions
function angleBetween(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
function distanceBetween(x1, y1, x2, y2) {
return Math.abs(y2 - y1) + Math.abs(x2 - x1);
}
//Draw function
function draw() {
//Loop through balls
for (var ballIndex1 = 0; ballIndex1 < balls.length; ballIndex1++) {
var ball1 = balls[ballIndex1];
//Collide with horisontal wall
if (ball1.xPos > width - ball1.size || ball1.xPos < 0) {
ball1.xAcc = -ball1.xAcc;
}
//Collide with vertical wall
if (ball1.yPos > height - ball1.size || ball1.yPos < 0) {
ball1.yAcc = -ball1.yAcc;
}
//Collide with other balls
for (var ballIndex2 = ballIndex1 + 1; ballIndex2 < balls.length; ballIndex2++) {
var ball2 = balls[ballIndex2];
//Test within collision distance
if (distanceBetween(ball1.xPos, ball1.yPos, ball2.xPos, ball2.yPos) > ball1.size) {
continue;
}
//Get angle of collision
var angle = angleBetween(ball1.xPos, ball1.yPos, ball2.xPos, ball2.yPos);
//Apply force to acceleration
ball1.xAcc = -Math.cos(angle) * 3;
ball2.xAcc = -ball1.xAcc;
ball1.yAcc = -Math.sin(angle) * 3;
ball2.yAcc = -ball1.yAcc;
}
//Apply acceleration to position
ball1.yPos += ball1.yAcc;
ball1.xPos += ball1.xAcc;
//Apply to node
ball1.HTMLNode.style.left = ball1.xPos + "px";
ball1.HTMLNode.style.top = ball1.yPos + "px";
}
}
//Start simulation
setInterval(draw, 1000 / 60);
.circle {
position: absolute;
border-radius: 50%;
height: 50px;
width: 50px;
}
.container {
height: 300px;
width: 300px;
background-color: skyblue;
position: relative;
}
<div class="container" id="container">
<div class="circle" id="circle1" style="background-color:black;
top:0; left:0"></div>
<div class="circle" id="circle2" style="background-color:rgb(197, 100,
100);top:200px;left: 150px"></div>
<div class="circle" id="circle3" style="background-color:brown;top:50px;left: 640px"></div>
</div>

Calling a jQuery function on an external file for all the images on a page

I was trying to make a web page with images, which should provide the exact functionality of other pages on the same site. I could do that, except image enlarging feature on it.
Images should be enlarged on a popped-up box. For that, on the other pages a js file is used. (Attached)
The way I have tried is below. Since the other pages' codes are messy I couldn't grab exact thing to do. Help on this is much appreciated.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
$(window).load(function() {
var productThumbImage = $('.search_holder .product-enlarge-trigger img');
productThumbImage.each(function() {
// Get on screen image
var screenImage = $(this);
// Create new offscreen image to test
var theImage = new Image();
theImage.src = screenImage.attr("src");
// Get accurate measurements from that.
var imageWidth = theImage.width;
var imageHeight = theImage.height;
if (imageWidth > imageHeight) {
$(this).addClass('thumbCheckLandscape');
}
});
});
$(".product-enlarge-trigger img").hover(function() {
alert('aaa');
});
$('body').removeClass();
detectThumbs();
function detectThumbs() {
var productThumbImage = $('.product-enlarge-trigger img');
alert(productThumbImage);
productThumbImage.each(function() {
var thumbCheck = $(this).attr('src');
thumbCheck = thumbCheck.split('/');
thumbCheck = thumbCheck[2];
thumbCheck = thumbCheck.replace("%20", "");;
$(this).parent().addClass(thumbCheck);
});
}
</script>
<script type="text/javascript" src="JS/Enlarge/image.enlarge.js"></script>
<style type="text/css">
.tablet_thumb_landscape.thumbCheckLandscape {
margin-top: 16px;
width: 117px !important;
}
.thumbCheckLandscape {
width: 100% !important;
}
.product-enlarge-trigger img {
width: 7%;
position: static !important;
}
.item_thumb_wrapper {
height: 186px;
-webkit-box-shadow: inset 0px -15px 0px 0px rgba(218, 218, 218, 0.99);
-moz-box-shadow: inset 0px -15px 0px 0px rgba(218, 218, 218, 0.99);
box-shadow: inset 0px -15px 0px 0px rgba(218, 218, 218, 0.99);
padding-bottom: 8px;
border-bottom: 8px solid #c8c7c8;
margin-bottom: 8px;
position: relative;
}
.enlarge_thumb_close {
width: 33px;
height: 33px;
right: -16px;
top: -16px;
position: absolute;
display: block;
background: url(../../../Images/Structure/search_enlarge_close.png)top left no-repeat;
background-size: 100%;
z-index: 1001 !important;
}
</style>
</head>
<body>
<div class="item_thumb_wrapper">
<img src="aa\xxx.jpg" class="resize" width="250" />
</div>
<div class="product-enlarge-trigger">
<img src="aa\xxx.jpg" class="resize" width="250" />
</div>
<div class="box">
<img src="aa\xxx.jpg" class="resize" width="250" />
</div>
</body>
</html>
External js file
// Plugin Definition
$.fn.productEnlarge = function(options) {
var defaults = {
'fadeInSpeed': 300,
'lastRowClass': 'last',
'overlayDiv': 'item-overlay-global',
'enlargeDiv': 'product-scroll-enlarge'
}
// Extend our default options with those provided
var opts = $.extend({}, defaults, options);
var getScrollTop = function() {
var ScrollTop = document.body.scrollTop;
if (ScrollTop == 0) {
if (window.pageYOffset)
ScrollTop = window.pageYOffset;
else
ScrollTop = (document.body.parentElement) ? document.body.parentElement.scrollTop : 0;
}
return ScrollTop;
}
var getViewportHeight = function() {
var viewportheight;
// the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
if (typeof window.innerWidth != 'undefined') {
viewportheight = window.innerHeight
}
// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth !=
'undefined' && document.documentElement.clientWidth != 0) {
viewportheight = document.documentElement.clientHeight
}
// older versions of IE
else {
viewportheight = document.getElementsByTagName('body')[0].clientHeight
}
return viewportheight;
}
/*** sniff the UA of the client and show hidden div's for that device ***/
var ua = navigator.userAgent;
var windowwidth = $(window).width();
var checker = {
android: ua.match(/Android/),
appleiPad: ua.match(/iPad/)
};
if (windowwidth <= 660) {
//if (checker.android){
// do nothing
} // end UA detection
else {
// For every trigger passed bind our events
return this.each(function() {
$this = $(this);
$this.mouseover(function() {
var hover_link = $(this).parent().attr('href');
//var hover_call = $(this).parent().attr('rel');
var hover_call = $(this).attr('rel');
//alert (hover_link);
// Create our overlay div
//$('body').append('<a class="enlarge_thumb_close">Close</a>');
$('body').append('');
$(this).parent().parent().find('.card-link').addClass('cardTitleSelected');
//$(this).parent().parent().find('.card-link').appendTo('.product-scroll-enlarge');
//$('.cardTitleSelected').appendTo('.product-scroll-enlarge');
//$('.cardTitleSelected').show();
var product_target_title = $(this).parent().parent().find('.card-link span');
//$('.product-scroll-enlarge').append('<div class="enlarge_title"><div class="et_text_wrap">'+ product_target_title.html() +'<br><strong>A6</strong> £1.79 / <strong>A4</strong> £2.99 / <strong>A3</strong> £5.99</div></div>');
$('.enlarge_title').hide().remove();
$('.product-scroll-enlarge').append('<div class="enlarge_title"><div class="et_text_wrap">' + product_target_title.html() + '</div></div>');
//alert(product_target_title.html());
$('body').append('<div class="enlarge_thumb_close"></div>');
// Get our targets
var target = $('.' + opts.overlayDiv);
// Set a fallback bind to remove this new target on mouseout
target.mouseout(function() {
$(this).remove();
});
var product_target = $(this).parent().parent().parent().find('.' + opts.enlargeDiv);
if (product_target.length == 0) {
return false;
}
$(target).html(product_target.html()).fadeIn(opts.fadeInSpeed);
// Calculate our positioning
var pos_top = (($(this).offset().top + ($(this).height() / 2)) - (target.height() / 2));
var pos_left = $(this).offset().left + $(this).width() + 25;
var totalwidth = pos_left + target.width() + 25;
// If our image goes beyond our viewport width or has a class of 'last' flip our offset
if ($(this).parent().hasClass(opts.lastRowClass) || totalwidth > document.body.offsetWidth) {
pos_left = ($(this).offset().left - target.width()) - 30;
}
var totalheight = (pos_top - getScrollTop()) + parseInt(target.height());
//var totalheight = ((pos_top - getScrollTop()) + ($(this).height() / 2)) - parseInt(taget.height() / 2);
var windowHeight = getViewportHeight();
// If our image goes beyond our window height
if (totalheight > windowHeight) {
var minusval = parseInt(totalheight) - windowHeight;
pos_top = pos_top - (minusval + 30);
}
// If our image is less than the product height, display below
if (totalheight < target.height()) {
pos_top = getScrollTop() + 50;
}
// Set our positional coordinates
$(target).css('top', pos_top).css('left', pos_left);
setTimeout(function() {
//do something special
var mainimagewidth = $('.item-overlay-global img').width();
$('.enlarge_thumb_close').css('top', pos_top - 16).css('left', pos_left + mainimagewidth - 16);
}, 100);
$('.enlarge_thumb_close').click(function() {
$this.hide().remove();
$('.' + opts.overlayDiv).hide().remove();
$('.enlarge_thumb_close').hide().remove();
});
});
$this.mouseout(function() {
var windowwidth = $(window).width();
var ua = navigator.userAgent;
var checker = {
appleiPad: ua.match(/iPad/)
};
if (windowwidth <= 440 || checker.appleiPad) {
} else {
$('.' + opts.overlayDiv).hide().remove();
$('.enlarge_thumb_close').hide().remove();
$('.enlarge_title').hide().remove();
}
//$('.cardTitleSelected').appendTo('.product-scroll-enlarge');
//$('.cardTitleSelected').hide();
//$('.product-scroll-enlarge .cardTitleSelected').after(''+ $this +' .shortlistSave');
});
$('.enlarge_thumb_close').click(function() {
$('.' + opts.overlayDiv).hide().remove();
$('.enlarge_thumb_close').hide().remove();
$('.enlarge_title').hide().remove();
});
$('.item-overlay-global').click(function() {
window.location = hover_link;
});
});
}
};

How do I make text resizable to browser?

So I want to make the word "WIDTH" resize according to the width of the browser. Right now, only the box around the word resizes, but I want the word to resize as well. I feel like there's something wrong with my calculations.
<!DOCTYPE html>
<html>
<head>
<style>
#header{
margin: 0px;
font-size: 200px;
display:inline;
padding:0px;
position:absolute;
white-space:nowrap;
overflow:hidden;
border:thin solid black;
height:800px;
}
</style>
</head>
<body style="padding:0px;">
<div id="header"> WIDTH </div>
<script>
var text_div = document.getElementById("header");
var size = function (){
var winW = window.innerWidth;
var winH = window.innerHeight;
var win_ratio = winW/winH;
var offset_width = text_div.offsetParent.clientWidth;
var offset_height = text_div.clientHeight;
var offset_ratio = offset_width / offset_height;
text_div.style.width = offset_width + "px";
document.title = winW + ":" + offset_height;
text_div.style.fontSize=String(parseInt(winW/offset_ratio)) + "px";
}
window.onresize=function() {size();}
//size();
</script>
</body>
</html>
If you wrap your text in a span, you can get the text's offsetWidth
<div id="header"><span>WIDTH</span></div>
The div's width is fixed with left: 0px and right: 0px
#header {
position: absolute;
left: 0px;
right: 0px;
border: 1px solid black;
}
and the font-size is then adjusted dynamically. The for is there to prevent an endless loop
var epsilon = 5;
var div = document.getElementById('header');
var span = div.childNodes[0];
function size() {
var dw = div.offsetWidth;
var fs = 200;
span.style.fontSize = fs + 'px';
var cw = span.offsetWidth;
for (var i = 0; i < 10 && Math.abs(cw - dw) > epsilon; ++i) {
fs *= dw / cw;
span.style.fontSize = fs + 'px';
cw = span.offsetWidth;
}
}
window.onresize = size;
size();
JSFiddle
I'm not sure why you were using all the ratio stuff. Here's a simple example based on width alone.
http://jsfiddle.net/tHBpJ/3
var text_div = document.getElementById("header");
var initWinW = window.innerWidth;
var initFontSize = 40;
var size = function () {
var winW = window.innerWidth;
var textFactor = winW / initWinW
text_div.style.fontSize = initFontSize * textFactor + "px";
}
window.onresize = function () {
size();
}
I've used the jquery plugin fittext.js for this kind of thing in the past, and its worked quite nicely.

Why don't Firefox, Chrome, Opera keep up with mouse events?

Why can't modern browsers keep up with the mouse? Firefox 3.6, Chrome 8.xx, Opera 10.xx, all fail to fire mouse events like mouseover, mouseout and mousemove at anything like a high enough rate to keep up with a fast moving mouse.
How does the browser decide when to generate a mouseover or mouseout event under these conditions? In practice it bears no resemblance to the accepted definition of "This mouseout event is sent to an element when the user moves the mouse outside the element. This event is the reverse of mouseover." [MDC]
The code below is the simplest case I can find to demonstrate this behaviour. Event listeners are attached to the document object.
<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml"
xml:lang="en" lang="en" >
<head>
<title>Mouse event tracking</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<style type="text/css">
div {
position: absolute;
border: 1px solid black;
width: 40px;
height: 100px;
}
</style>
</head>
<body>
<h1 style="position: absolute; top: 10px; left: 10px; font-size: 14px">Start on green, move mouse to yellow</h1>
<div id="ladder_start" style="top: 50px; left: 10px; background-color: #44ff44;"></div>
<div id="ladder" style="top: 50px; left: 50px;"></div>
<div id="ladder_end" style="top: 50px; left: 850px; background-color: #ffff44;"></div>
<div id="ladder_p_over" style="top: 50px; left: 900px; width: 100px; height: 50px"></div>
<div id="ladder_p_out" style="top: 100px; left: 900px; width: 100px; height: 50px"></div>
<canvas id="ladder_trace" style="position: absolute; border: 1px solid black; top: 155px; left: 50px; height: 20px"></canvas>
<script type="text/javascript">
window.addEventListener("load", function (event) {
if (window.event_tests_loaded === true) {
return;
}
var ladder = document.getElementById("ladder");
var ladder_trace = document.getElementById("ladder_trace");
var ladder_start = document.getElementById("ladder_start");
var ladder_end = document.getElementById("ladder_end");
var ladder_p_over = document.getElementById("ladder_p_over");
var ladder_p_out = document.getElementById("ladder_p_out");
var mouse_over_count = 0;
var mouse_out_count = 0;
var steps = [];
var trace = ladder_trace.getContext('2d');
var step_over = function (event) {
event.preventDefault();
event.stopPropagation();
if (typeof event.target.parentNode === "object") {
if (event.target.parentNode === ladder) {
event.target.style.backgroundColor = event.target.highlight_color;
mouse_over_count++;
ladder_p_over.textContent = mouse_over_count;
}
}
};
var step_out = function (event) {
event.preventDefault();
event.stopPropagation();
if (typeof event.target.parentNode === "object") {
if (event.target.parentNode === ladder) {
mouse_out_count++;
ladder_p_out.textContent = mouse_out_count;
}
}
};
var move = function (event) {
event.preventDefault();
event.stopPropagation();
if ((event.clientX >= 50) && (event.clientX < 850)) {
trace.fillStyle = "black";
trace.strokeStyle = "black";
trace.lineWidth = 1;
trace.beginPath();
trace.moveTo(event.clientX - 50 + 0.5, 0);
trace.lineTo(event.clientX - 50 + 0.5, 20);
trace.stroke();
}
};
ladder_start.addEventListener("mouseover", function (event) {
event.preventDefault();
event.stopPropagation();
mouse_over_count = 0;
mouse_out_count = 0;
ladder_p_over.textContent = mouse_over_count;
ladder_p_out.textContent = mouse_out_count;
var i;
for (i = 0; i < 40; i++) {
steps[i].style.backgroundColor = steps[i].original_color;
}
trace.clearRect(0, 0, 800, 20);
document.addEventListener("mouseover", step_over, false);
document.addEventListener("mouseout", step_out, false);
document.addEventListener("mousemove", move, false);
}, false);
ladder_end.addEventListener("mouseover", function (event) {
document.removeEventListener("mouseover", step_over, false);
document.removeEventListener("mouseout", step_out, false);
document.removeEventListener("mousemove", move, false);
}, false);
(function () {
var i;
for (i = 0; i < 40; i++) {
steps[i] = document.createElement("div");
steps[i].style.width = "20px";
steps[i].style.border = "0";
steps[i].style.top = "0px";
steps[i].style.left = (i * 20) + "px";
steps[i].original_color = "rgb(" + (i * 4) + ",0,0)";
steps[i].highlight_color = "rgb(255," + (i * 4) + ",255)";
steps[i].style.backgroundColor = steps[i].original_color;
ladder.appendChild(steps[i]);
}
ladder.style.width = (i * 20) + "px";
ladder_trace.style.width = (i * 20) + "px";
ladder_trace.width = (i * 20);
ladder_trace.height = 20;
}());
ladder_p_over.textContent = mouse_over_count;
ladder_p_out.textContent = mouse_out_count;
}, false);
</script>
</body>
</html>
That would be because they render first, and then check for input.
I've been frustrated about this for a while too, but a few tests confirmed this.
They render and then check for input.
Edit: If you have a good computer and use a good recording software, try recording your mouse in your monitor's full FPS. Now play it in slow motion, like 1/10 speed.
You'll notice that the mouse cursor doesn't pass through every pixel on the screen. If it did, it could either...
Go through every pixel, every frame.
This would limit your mouse speed (pixels/second) to your monitor's FPS (hertz).
Virtually go through every pixel in a sub-frame manner.
This would definitely take much processor time to think.
To fix this, every OS makes the mouse jump/skip to the required pixel every frame.
... and thus, your problem.

Categories

Resources