How to add fade effect while changing CSS with JQuery - javascript

I am faking fixed position for a footer on a mobile site for mobile browsers that don't support fixed-position. (iOS before iOS 5, Andriod before 2.2, etc.)
Here is the JQuery code I'm using, which works well and does what I want:
function changeFooterPosition() {
$('.not-fixed').css('top', window.innerHeight + window.scrollY - 56 + "px");
}
$(document).bind('scroll', function() {
changeFooterPosition();
});
So that works.
My question is, I want to add a slight delay to it and have the footer fade into view rather than just snap quickly after every little scroll. I've looked around and found the following methods I could use, but I"m not sure if they are the correct ones or where to add them to the js above.
.delay(1000).fadeTo('slow', 1)
I know this functionality exists in JQuery Mobile, but I don't want to use the entirety of JQuery Mobile for just this one little thing.
Thanks in advance.

Try the animate function http://api.jquery.com/animate/
This won't fade but should move smoothly instead.
function changeFooterPosition() {
$('.not-fixed').animate({'top': window.innerHeight + window.scrollY - 56 + "px"}, 2000);
}
$(document).bind('scroll', changeFooterPosition);

Change
$(document).bind('scroll', function() {
changeFooterPosition();
});
To
$(document).bind('scroll', changeFooterPosition);
Change
$('.not-fixed').css('top', window.innerHeight + window.scrollY - 56 + "px");
to
var WantedSpeed = 2000;
$('.not-fixed').delay(1000).animate({
top: window.innerHeight + window.scrollY - 56 + "px"
}, WantedSpeed, function() {
// Animation complete.
})

What you want to do is throttle your scroll callback:
(function() {
var scrollTimer = 0,
$notFixed = $('.not-fixed');
function changeFooterPosition() {
$notFixed.css('top', window.innerHeight + window.scrollY - 56 + "px").show(300);
}
$(document).bind('scroll', function() {
$notFixed.hide();
clearTimeout(scrollTimer);
setTimeout(changeFooterPosition, 50);
});
}());

Related

Converting an example jQuery function to vanilla JS: apparent trouble with Element.offsetTop

I'm not even sure exactly what I'm asking, so bear with me.
I'm trying to replicate the effect in this cool pen from Krz Szzz
Here's the original jQuery:
$('.tile')
// tile mouse actions
.on('mouseover', function(){
$(this).children('.photo').css({'transform': 'scale('+ $(this).attr('data-
scale') +')'});
})
.on('mouseout', function(){
$(this).children('.photo').css({'transform': 'scale(1)'});
})
.on('mousemove', function(e){
$(this).children('.photo').css({'transform-origin': ((e.pageX -
$(this).offset().left) / $(this).width()) * 100 + '% ' + ((e.pageY -
$(this).offset().top) / $(this).height()) * 100 +'%'});
})
And here's my attempt to nativize the jQuery (I've tried to reduce the complexity to focus on the issue at hand, so my markup is a bit different than his/hers, but not in relevant ways, I don't believe).
var tile = document.querySelector('.tile');
var tileWidth = tile.offsetWidth;
var tileHeight = tile.offsetHeight;
var tileTop = tile.offsetTop;
var tileLeft = tile.offsetLeft;
tile.addEventListener('mouseover', function(){
tile.style.transform = "scale(1.5)";
});
tile.addEventListener('mousemove', function(e){
tile.style.transformOrigin = ((e.pageX - tileLeft) / tileWidth) * 100 + "%" + ((e.pageY - tileTop) / tileHeight) * 100 + "%";
});
tile.addEventListener('mouseout', function(){
tile.style.transform = "scale(1)";
});
My version halfway works. But there's a calculation error somewhere in there that prevents setting the correct value for the second parameter of the transform-origin CSS.
I believe the issue has to do with $(this).offset().top in the jQuery. I've converted this to Element.offsetTop, but that may not be correct. I've burned 1.5 hours trying to learn my way to success here on SO, but I'm not making any headway.
Any pointers in the right direction would be greatly appreciated.
jQuery offset().top() gets coords related to the document while js offsetTop is related to the parentNode.
You may give Element.getBoundingClientRect().top a try.
It'll give you the top position related to the viewport, not to the document. But it's a beginning.
Then, you can get the scroll position with document.documentElement.scrollTop and sum both of them.
PS: document.documentElement.scrollTop doesn't work on Safari, as I'm concerned. Use document.body.scrollTop instead.

Transition animation bug

If i use in showAnimateWin property offsetHeight, animation work. example
function end( ) {
var top = ( window.innerHeight - win.clientHeight ) / 2,
left = ( window.innerWidth - win.clientWidth ) / 2;
win.style.top = top + "px";
win.style.left = left + "px";
}
function showAnimateWin( ) {
win.offsetHeight ;//here
win.classList.add("modal-window-animate");
end();
};
If i removed win.offsetHeight, animation work only one times. example
function showAnimateWin( ) {
win.classList.add("modal-window-animate");
end();
};
Why won't work without win.offsetHeight ?
The reason is probably because the win.offsetHeight; causes the method to wait for a few milliseconds before the transition can start again. If you put alert(1); instead of the win.offsetHeight; it will still work. You need to wait for the transition to complete before starting another animation.
UPDATE: Fiddle Link
This should work without having any delays (check fiddle):
window.setTimeout(function() {
showAnimateWin();
}, 25);

Window vertically re-sizing issue

Im trying to resize the window. it works horizentally but not vertically. What am I doing wrong here:
$(window).resize(resizeWebSite());
function resizeWebSite(){
$("#panel").height($(window).height() - 10);
$("#map").height($(window).height() - 10);
console.log($("#map").height() / 2);
var loaderTop = ($("#map").height() - $("#loadingIndicator").height()) / 100 + $("#map").position().top;
var loaderLeft = (($("#map").width() - $("#loadingIndicator").width()) / 100) + $("#map").position().left;
$("#loadingIndicator").css({'position' : 'absolute' , 'left' : loaderLeft + 'px', 'top' : loaderTop + 'px'});
}
resizeWebSite();
When you set up the event handler, you need to pass only the name of the function:
$(window).resize(resizeWebSite);
Now a further problem with this will be that on a desktop/laptop machine (traditional computer, as opposed to a tablet), where the user can resize the browser window interactively, the browser will fire "resize" events very rapidly. All that work inside the handler will make the response very sluggish and jumpy.
To counteract that, you can use a timer. The idea is to respond to a "resize" event by first cancelling any pending timer, and then setting a new timer for some time in the future (a hundred milliseconds or so) to run the actual code that deals with the new window size. That way, while the user is moving the mouse quickly to change the window size, the only work you're doing is clearing and resetting a timer, which is pretty fast. Only when the user stops moving the mouse for a while do you actually do any real work.
That would look something like this:
var resizeTimer = null;
$(window).resize(function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(resizeWebSite, 100);
});
Maybe this is what you're after?
function resizeWebSite(){
$("#panel").height($(window).height() - 10);
$("#map").height($(window).height() - 10);
console.log($("#map").height() / 2);
var loaderTop = ($("#map").height() - $("#loadingIndicator").height()) / 100 + $("#map").position().top;
var loaderLeft = (($("#map").width() - $("#loadingIndicator").width()) / 100) + $("#map").position().left;
$("#loadingIndicator").css({'position' : 'absolute' , 'left' : loaderLeft + 'px', 'top' : loaderTop + 'px'});
}
$(document).ready(resizeWebSite);
$(window).resize(resizeWebSite);
By the way, if you're using margin on the elements you're reading the height on, and you want to include them in the calculations, use outerWidth(true) instead of width()

Hide address bar not working - bulletproof approach needed

At the moment I am writing some kind of web app and I want to hide the address bar on iOS devices and preferably also on Android devices.
Normally I do this with
window.addEventListener( 'load', function () {
setTimeout( function () {
window.scrollTo( 0, 1 );
}, 0 );
});
but this won't work now because the page hasn't enough content to scroll.
Now I know this is a common problem and I know that there are multiple solutions, but I would prefer a small, bulletproof solution.
Actually I was quite happy when I found this question: http://stackoverflow.com/questions/9678194/cross-platform-method-for-removing-the-address-bar-in-a-mobile-web-app
where this code was posted:
function hideAddressBar()
{
if(!window.location.hash)
{
if(document.height < window.outerHeight)
{
document.body.style.height = (window.outerHeight + 50) + 'px';
}
setTimeout( function(){ window.scrollTo(0, 1); }, 50 );
}
}
window.addEventListener("load", function(){ if(!window.pageYOffset){ hideAddressBar(); } } );
window.addEventListener("orientationchange", hideAddressBar );
Unfortunately, this doesn't work for me. I see that something happens because some elements that have padding-top set in percentages move down, but the address bar stays.
Of course I also did a Google search and tried many snippets I found. Some did nothing, some just moved the elements with padding-top down a bit.
The only working code I found is this:
var page = document.getElementById('page'),
ua = navigator.userAgent,
iphone = ~ua.indexOf('iPhone') || ~ua.indexOf('iPod'),
ipad = ~ua.indexOf('iPad'),
ios = iphone || ipad,
// Detect if this is running as a fullscreen app from the homescreen
fullscreen = window.navigator.standalone,
android = ~ua.indexOf('Android'),
lastWidth = 0;
if (android) {
// Android's browser adds the scroll position to the innerHeight, just to
// make this really difficult. Thus, once we are scrolled, the
// page height value needs to be corrected in case the page is loaded
// when already scrolled down. The pageYOffset is of no use, since it always
// returns 0 while the address bar is displayed.
window.onscroll = function() {
page.style.height = window.innerHeight + 'px'
}
}
var setupScroll = window.onload = function() {
// Start out by adding the height of the location bar to the width, so that
// we can scroll past it
if (ios) {
// iOS reliably returns the innerWindow size for documentElement.clientHeight
// but window.innerHeight is sometimes the wrong value after rotating
// the orientation
var height = document.documentElement.clientHeight;
// Only add extra padding to the height on iphone / ipod, since the ipad
// browser doesn't scroll off the location bar.
if (iphone && !fullscreen) height += 60;
page.style.height = height + 'px';
} else if (android) {
// The stock Android browser has a location bar height of 56 pixels, but
// this very likely could be broken in other Android browsers.
page.style.height = (window.innerHeight + 56) + 'px'
}
// Scroll after a timeout, since iOS will scroll to the top of the page
// after it fires the onload event
setTimeout(scrollTo, 0, 0, 1);
};
(window.onresize = function() {
var pageWidth = page.offsetWidth;
// Android doesn't support orientation change, so check for when the width
// changes to figure out when the orientation changes
if (lastWidth == pageWidth) return;
lastWidth = pageWidth;
setupScroll();
})();
Source
But I am not really happy with this solution as I am not a friend of UA sniffing.
Do you have any suggestions what I could try to make it work without UA sniffing? Can it be my HTML that causes problems with some scripts I posted?
Don't know if it's bulletproof, but it works on a bunch of devices. If you find caveat, let me know.
if (((/iphone/gi).test(navigator.userAgent) || (/ipod/gi).test(navigator.userAgent)) &&
(!("standalone" in window.navigator) && !window.navigator.standalone)) {
offset = 60;
$('body').css('min-height', (window.innerHeight + offset) + 'px');
setTimeout( function(){ window.scrollTo(0, 1); }, 1 );
}
if ((/android/gi).test(navigator.userAgent)) {
offset = 56;
$('html').css('min-height', (window.innerHeight + offset) + 'px');
setTimeout( function(){ window.scrollTo(0, 1); }, 0 );
}

Slow scrolling background in Javascript or CSS?

I'm trying to figure out how to make a background image scroll slower than the page contents. I haven't got a clue how it's done. The perfect example of what I'm trying to do is here
Is this done in CSS or jQuery/Javascript?
This is made by javascript (jQuery):
(function () {
var a = document.body,
e = document.documentElement;
$(window).unbind("scroll").scroll(function () {
a.style.backgroundPosition = "0px " + -(Math.max(e.scrollTop, a.scrollTop) / 8) + "px";
});
})();
The effect on the link you posted is done in Javascript using jQuery.
If you examine the code of a script of the site here, you can find:
.style.backgroundPosition="0px "+-(Math.max(e.scrollTop,a.scrollTop)/8)+"px"
Practically, the background-position CSS property is modified on page scrolling calculating Y-axis depending on page scroll position. If you have some knowledge of Javascript, jQuery or Mootools, you can reproduce the effect very easily.
I think it's impossible to do it using only CSS.
This one works for high bg images.
(function () {
var body = document.body,
e = document.documentElement,
scrollPercent;
$(window).unbind("scroll").scroll(function () {
scrollPercent = 100 * $(window).scrollTop() / ($(document).height() - $(window).height());
body.style.backgroundPosition = "0px " + scrollPercent + "%";
});
})();

Categories

Resources