How do i get relative dimensions of scrollbale window viewport - javascript

I am having a Tooltip (larger image view) that is being positioned via e.pageX e.pageY and i am trying to make sure it is not hidden below the current scrolled view port.
I have seen many sites have this
my code is something like this but i am missing something.
var positionImg = function(e) {
var viewportWidth = $(window).width();
var viewportHeight = window.innerHeight ? window.innerHeight : $(window).height();
var mouseAtY = e.pageY;
var mouseAtX = e.pageX;
var maxBottomVPos = viewportHeight-"i dont know";
var maxTopVPos = 30;
if (mouseAtY >= maxBottomVPos)
{
tPosX = mouseAtX+ 10;
tPosY = mouseAtY -520;
}
else if (mouseAtY <= maxTopVPos)
{
tPosX = mouseAtX;
tPosY = mouseAtY +40;
}
else
{
tPosX = mouseAtX;
tPosY = mouseAtY +20;
}
$zoomContainer.css({top: tPosY, left: tPosX});
};

var maxBottomVPos = viewportHeight-"i dont know";
You probably don't want to go any lower than the height of the element that you are positioning. So use the height of zoomContainer to figure out how much higher it needs to go. This way, the whole thing can be included. Of course, you'll have to consider that the user might shrink the screen too small to fit the container.
To get the scroll offset use scrollTop. With this you will have both the size of the viewport and how far down the viewport is.

I found the answer:
Quite simple:
var positionImg = function(e) {
cntnrH = $zoomContainer.height() + 230;
calHight = e.pageY - $(window).scrollTop() + cntnrH;
docH = $(window).height()
var mouseAtY = e.pageY;
var mouseAtX = e.pageX;
if (calHight >= docH)
{
tPosX = mouseAtX + 5;
tPosY = mouseAtY - cntnrH;
}
else if (calHight <= calHight){
tPosX = mouseAtX;
tPosY = mouseAtY + 15;
}
else
{
tPosX = mouseAtX;
tPosY = mouseAtY +20;
}
$zoomContainer.css({top: tPosY, left: tPosX});
};
doIt = $("img.hovelble");
doIt.hover(showZoomImg, hideZoomImg).mousemove(positionImg);
});

Related

How can I write jquery plugin that works on multiple elements

I wrote following functon and I am trying to use that in different elements but it doesn't work.
$.fn.sticky = function() {
var
scrollTop = $(window).scrollTop();
replace_class = $(this),
sticky = "ceras_sticky_header",
elementOffset = replace_class.offset().top,
distance = (elementOffset - scrollTop),
leftPositionofImage = replace_class.offset().left,
windowWidth = $(window).width(),
elementWidth = replace_class.width(),
rightPosition = (windowWidth - leftPositionofImage - elementWidth - 12);
$(window).scroll(function() {
if( $(this).scrollTop() > distance) {
replace_class.addClass(sticky);
replace_class.css('right',rightPosition);
replace_class.draggable();
} else {
replace_class.removeClass(sticky);
}
});
};
I want to it to work like:
$( ".ancor_controls" ).sticky();
$( ".ancor_controls1" ).sticky();

variable used out of scope

I'm doing a responsive background video. I have this code.
<video id="bgvideo" />
function scaleVideo() {
var windowHeight = $(window).height();
var windowWidth = $(window).width();
var videoNativeWidth = $('video#bgvideo')[0].videoWidth;
var videoNativeHeight = $('video#bgvideo')[0].videoHeight;
var heightScaleFactor = windowHeight / videoNativeHeight;
var widthScaleFactor = windowWidth / videoNativeWidth;
if (widthScaleFactor >= heightScaleFactor) {
var scale = widthScaleFactor;
} else {
var scale = heightScaleFactor;
}
var scaledVideoHeight = videoNativeHeight * scale;
var scaledVideoWidth = videoNativeWidth * scale;
$('video#bgvideo').height(scaledVideoHeight);
$('video#bgvideo').width(scaledVideoWidth);
}
I'm using grunt to compile my code and etc.
Jshint of grunt is saying I'm using "scale" out of scope and I cant understand why.
Any suggests ?
You should not write var scale = heightScaleFactor; inside the else statement if you want to use it outside of it.
Initialize scale outside the if
var scale;
if (widthScaleFactor >= heightScaleFactor) {
scale = widthScaleFactor;
} else {
scale = heightScaleFactor;
}
Try this instead:
function scaleVideo() {
var scale; //this is the change
var windowHeight = $(window).height();
var windowWidth = $(window).width();
var videoNativeWidth = $('video#bgvideo')[0].videoWidth;
var videoNativeHeight = $('video#bgvideo')[0].videoHeight;
var heightScaleFactor = windowHeight / videoNativeHeight;
var widthScaleFactor = windowWidth / videoNativeWidth;
if (widthScaleFactor >= heightScaleFactor) {
scale = widthScaleFactor; //simply modify the value here
} else {
scale = heightScaleFactor;
}
var scaledVideoHeight = videoNativeHeight * scale;
var scaledVideoWidth = videoNativeWidth * scale;
$('video#bgvideo').height(scaledVideoHeight);
$('video#bgvideo').width(scaledVideoWidth);
}

select specific area of a div

I made a carousel using 2 divs named "left" and "right" putting mousemove events on them. I wanted to make it go up and down as well so I created a "top" and "bottom" and noticed that I couldn't make them combine to go the way the cursor goes.
I thus thought of targeting a specific area in the container (i.e top half of my container div) instead of creating divs inside triggering a specific direction, this way (I think) I can trigger all these event altogether. However after now hours of research I couldn't find a way to do so.
How should I proceed ? here is the code : http://jsfiddle.net/pool4/vL5g3/3/
var x=0,
y=0,
rateX=0,
rateY=0,
maxspeed=10;
var backdrop = $('.backdrop');
$('.directionx', backdrop).mousemove(function(e){
var $this = $(this);
var left = $this.is('.left');
var right = $this.is('.right');
if (left){
var w = $this.width();
rateX = (w - e.pageX - $this.offset().left + 1)/w;
}
else if (right){
var w = $this.width();
rateX = -(e.pageX - $this.offset().left + 1)/w;
}
});
$('.directiony', backdrop).mousemove(function(e){
var $this = $(this);
var top = $this.is('.top');
var bottom = $this.is('.bottom');
if (top){
var h = $this.height();
rateY = (h - e.pageY - $this.offset().top + 1)/h;
}
else if (bottom) {
var h = $this.height();
rateY = -(e.pageY - $this.offset().top + 1)/h;
}
});
backdrop.hover(
function(){
var scroller = setInterval( moveBackdrop, 30 );
$(this).data('scroller', scroller);
},
function(){
var scroller = $(this).data('scroller');
clearInterval( scroller );
}
);
function moveBackdrop(){
x += maxspeed * rateX;
y += maxspeed * rateY;
var newpos = x+'px '+y+'px';
backdrop.css('background-position',newpos);
}
Your problem is that the divs that control movement up and down are placed over the ones that control left and right, so the latter do not receive the mousemove event ever. Mouse events do not propagate through layers, even if they're transparent. I changed your code and CSS, so each div is in one of the corners. To make things easier, I've used data-* attributes so the direction controlled by each div is set in a declarative way, without the need to change the code. You'll see that the code is much simpler (and it could be simplified even more).
By the way, you could achieve this witout extra divs, just controlling where the cursor is (to the top, right, left or bottom of the center of the div).
backdrop.on('mousemove', '.dir', function(e){
var $this = $(this);
var direction = $(e.target).attr('data-direction');
var left = direction.indexOf('left') > - 1;
var right = direction.indexOf('right') > - 1;
var top = direction.indexOf('up') > - 1;
var bottom = direction.indexOf('down') > - 1;
if (left){
var w = $this.width();
rateX = (w - e.pageX - $this.offset().left + 1)/w;
}
else if (right){
var w = $this.width();
rateX = -(e.pageX - $this.offset().left + 1)/w;
}
if (top){
var h = $this.height();
rateY = (h - e.pageY - $this.offset().top + 1)/h;
}
else if (bottom) {
var h = $this.height();
rateY = -(e.pageY - $this.offset().top + 1)/h;
}
});
I've updated your fiddle.
EDIT In this new fiddle I do it without extra divs:
var w = backdrop.width() / 2;
var h = backdrop.height() / 2;
var center = {
x: backdrop.offset().left + backdrop.width() / 2,
y: backdrop.offset().top + backdrop.height() / 2
};
backdrop.on('mousemove', function(e){
var offsetX = e.pageX - center.x;
var offsetY = e.pageY - center.y;
rateX = -offsetX / w;
rateY = -offsetY / h;
});
backdrop.hover(
function(){
var scroller = $(this).data('scroller');
if (!scroller) {
scroller = setInterval( moveBackdrop, 30 );
$(this).data('scroller', scroller);
}
},
function(){
var scroller = $(this).data('scroller');
if (scroller) {
clearInterval( scroller );
$(this).data('scroller', null);
}
}
);
As you see, the mousmove handler is considerably simpler.
To avoid issue of children losing event could use just the one.
First HTML from 4 child divs to just one
<div class="backdrop">
<div class="direction"></div>
</div>
<div id="pos"></div>
Next Inside the mousemove find your relative position
//Get Relative Position
var relX = e.pageX - $this.offset().left;
var relY = e.pageY - $this.offset().top;
Get Relative Position as a percentage of width and put 50% of it in negative for direction
var w = $this.width();
rateX = ((relX / w) - 0.5) * -1;
var h = $this.height();
rateY = ((relY / h) - 0.5) * -1;
Fiddle

Why isn't Chrome running this Javascript?

The script works perfect in FF and IE, but not in Chrome. Could someone help med to locate the problem?
The if statmenst seems not to be runned when they are supposed to, they do nothing when the should.
var top = 285;
var bottom = 650;
var pageheight, maxscroll;
window.onload = function(){
pageheight = document.body.offsetHeight;
maxscroll = pageheight - (bottom+40);
}
window.onscroll = function(){
var element = document.getElementById("guide-menu");
if(window.pageYOffset < top){
element.style.position = "absolute";
element.style.top = "300px";
}
if(window.pageYOffset > top){
element.style.top = "10px";
element.style.position = "fixed";
element.style.marginTop = "0px";
}
if(window.pageYOffset > maxscroll){
element.style.position = "absolute";
element.style.marginTop = (pageheight - bottom - 40) + "px";
}
}
"top" has different meaning in chrome. Just try to rename top variable.
The "top" variable returns the topmost browser window. Chrome is the only major browser not supporting overriding this variable.
Renaming your variable to something like "myTop" works perfectly.
This code works well.
var myTop = 285;
var bottom = 650;
var pageheight, maxscroll;
window.onload = function(){
pageheight = document.body.offsetHeight;
maxscroll = pageheight - (bottom+40);
window.onscroll = function()
{
var element = document.getElementById("guide-menu");
if(window.pageYOffset < myTop)
{
element.style.position = "absolute";
element.style.top = "300px";
}
if(window.pageYOffset > myTop)
{
element.style.top = "10px";
element.style.position = "fixed";
element.style.marginTop = "0px";
}
if(window.pageYOffset > maxscroll)
{
element.style.position = "absolute";
element.style.marginTop = (pageheight - bottom - 40) + "px";
}
}
}
By the way, check that you are puting the right conditions for the IF statements. If you want a menu which scrolls with the webpage, then you have to exchange the two first if conditions.

$(window).resize(): Before

Is it possible of getting the width/height of browser each time BEFORE the resize() is triggered?
$(window).resize(function() {
});
This is due to I'm calculating the difference before/after browser has resize().
You would have to store the previous value, a little like this
var prevHeight = 0;
var prevWidth = 0;
$(document).ready(function() {
prevHeight = $(window).height();
prevWidth = $(window).width();
});
$(window).resize(function() {
var currentHeight = $(window).height();
var currentWidth = $(window).width();
//do difference stuff
prevHeight = currentHeight;
prevWidth = currentWidth;
});

Categories