I'm trying to create my own custom parallax plugin so that I am able to choose the direction the items transition off the screen and I'm just stuck at making sure that no matter how a user scrolls and no matter of the size of the window that the object disappears at the correct point.
Currently I have:
var lastScrollTop = 0;
var logoStartPos = $('.bg-logo').position().left;
$(function(){
$(window).scroll(function(){
var st = $(this).scrollTop();
if (st > lastScrollTop){
if($('.bg-logo').is(':in-viewport'))
$('.bg-logo').css({'left':($('.bg-logo').position().left+10) + "px"});
} else {
if($('.bg-logo').is(':in-viewport') && logoStartPos < $('.bg-logo').position().left)
$('.bg-logo').css({'left':($('.bg-logo').position().left-10) + "px"});
}
lastScrollTop = st;
});
});
As you can guess this only moves the item right until it goes off screen. This way has varied results because if I use the scroll wheel it take longer to disappear to if I use the scroll bar. I also have another problem in that if I use a mixture or have a different view port I get an different result all together.
Any tips or pointers to achieve the result I'm after?
An working example of my code is at http://motoring.egl.me.uk
Thanks Matt
A bit dated, but FYI...
In your jQuery initialize or ready event, you need to initialize each section, article, item or whatever it is (item.each) to instantiate a scroll function, so that each one has it's own scroll function.
this.each(function(index) {
Then in scroll function, only handle the event, if it is the 'current' section. You will need some way to determine which item is the 'current' one. Often this is done by saving each item's window size into a global array, and then using that compare to the current location.
Something like: (The way you designed your code will likely be very different)
// If this section is in view
if ( ($window.scrollTop() + $window.height()) > (topOffset) &&
( (topOffset + $self.height()) > $window.scrollTop() ) )
In this way, once one item goes off the screen, the next item should become 'current' and continue the scrolling.
Related
I need to implement a scroll function in my site.
When I will scroll down, document will be scrolled until a fixed position, which I want.
For example:
$(“.scroll-block”).scrollTop(250);
I realized this function. Pseudo-code:
when (scrollTop > 0)
do (scrollTop(250))
But then scroll is fixed. And any scroll-actions doesn’t work.
But I have three block. And I want to keep the possibility to scroll to all three blocks.
How can I do that?
P.S.: sorry for my terrible English. It’s my first post on this platform for communication.
P.S.S.: and first topic on English language.
Register a scroll callback like so:
jQuery(window).scroll(scrollCallback);
In the callback you can get the scroll position and do whatever you want at specific heights.
function scrollCallback(){
//gets the current windows scroll top value
var scrollPos = jQuery(window).scrollTop();
//get the position of the top of the elements you want to trigger actions on.
var first = jQuery('the-element-you-want-to-select1').position().top;
var second = jQuery('the-element-you-want-to-select2').position().top;
if(scrollPos > first){
//do something for first height
}else if(scrollPos > second){
//do something for second height
}
..
..
}
I have a product listing on my website and when hovering over the product an info div shows up. The only problem is that in some cases parts of the div fall outside of the browser window.
I need to check with Javascript if thats the case, and if so I need to assign a class to that particular div. I know how to do the last part, but I have no idea how to check if the whole div is visible.
Can anybody give me a suggestion how to handle this?
Your goal is to determine if your HTML element is in the viewport. If you're using jQuery - there are a few plugins tha handle this.
Jquery check if element is visible in viewport
http://opensource.teamdf.com/visible/examples/demo-basic.html
With the example above, you'd want to use detectPartial set to true -- so that you would know whether or not the thing is inside the viewport entirely.
//added by JG 3/10/2011, to extend selectors.
// Example:
//if ($('#whatever').is(':inView') ) {...}
jQuery.extend(jQuery.expr[':'], {
inView: function(a) {
var st = (document.documentElement.scrollTop || document.body.scrollTop),
ot = jQuery(a).offset().top,
wh = (window.innerHeight && window.innerHeight < jQuery(window).height()) ? window.innerHeight : jQuery(window).height();
return ot > st && (jQuery(a).height() + ot) < (st + wh);
}
});
I did that a number of years ago, based off of Remy Sharp's inview plugin (https://remysharp.com/2009/01/26/element-in-view-event-plugin) -- but these only check for vertical in-view, not horizontal (scrolling sideways/off the left or right).
I'm trying to accomplish the effects on this site, but I only need to move around a few things based on scrolling. My goal is for the basketball to go into the box, then after scrolling down a little bit the box goes onto the truck and the objects all go together horizontally across the page. Also, I want this to happen when you scroll down, not when you scroll up like in the current fiddle.
Here my current Fiddle, originally based on this Fiddle. Below is the js.
var fixedElement = false;
var changingMoment = 150;
$(window).scroll(function() {
// floatingContentMark lets us know where the element shall change from fixed to relative
// and vice versa
var distanceFromTop = $("#floatingContentMark").offset().top - $(this).scrollTop();
if ((distanceFromTop <= changingMoment && !fixedElement) ||
(distanceFromTop >= changingMoment && fixedElement))
{ // either we came from top or bottom, same function is called
fixedElement = !fixedElement;
$('#box').trigger('fixElement');
}
});
$('#box').bind('fixElement', function() {
if ($(this).css('position') != 'fixed') {
$(this).css('position', 'fixed') ;
$(this).css('top', changingMoment) ;
}
else {
$(this).css('position', 'relative') ;
$(this).css('top', 'auto') ;
}
}) ;
I think that your project will be a lot easier if you use a framework or jQuery Plugin for custom/parallax scrolling. A quick google search brings up several that will easily do what you want:
skrollr
scrollorama
scrollpath
sequence.js
stellar.js
scrolly
NikeBetterWorld
Scrolling Parallax
jarallax
superscrollarama
For some inspiration, check out the pages listed here.
I am trying to create an 'application' contained in a div on a web page. This can't be any larger than certain dimensions (lets say: 550px by 280px). I have a menu with at least 1-3 sub menus for each item. The problem is, while I know the submenu is no larger than 280px high, the submenus often extend beyond the parent div's bounds (except for the last one which always grows upward not down).
Is there any way to make the menus grow up or down depending on whether it will extend beyond the div's bounds?
Here is a JSFiddle: http://jsfiddle.net/3FqcG/
Notice how the "Salzburg" submenu grows down beyond the bounds of the black DIV? I want that to grow up if it is too long and down if there is enough room.
Currently, I am just using the basic initialization: $( "#menu" ).menu();
Thanks!
I don't believe you can do this in CSS.
This leaves us with javascript. The basic idea is to:
calculate the baseline of the menu
if this lies outside the boundary
move the menu upwards to correct the position
live almost happily ever after
But, we have one major issue:
Though we capture the focus of an element, we don't know when its submenu is displayed & positioned. So although your problem is technically solved, it is by far not a desirable solution.
UPDATE
The best workaround I could come up with was to:
Turn off the animation (to avoid ugly glitches)
Add a watcher that would constantly monitor the element that is about to be opened
If opened, apply the position correction
Anyway, if you consider coming this far, you might as well override the default positioning of the jquery ui component, with the note that you will not be able to easily update the library. Update: or try Rudy Garcia's version if it works
Demo
Code of the demo:
var BASE_OFFSET = $('#menuContainer').offset().top;
var MAX_OFFSET = $('#menuContainer').height(); // get the offset of the container
var whenVisible = function($el, callback){ //executes callback when $el is visible
if($el.is(':visible')){ // if visible
callback(); // execute callback
}else{ // otherwise
setTimeout(function(){whenVisible($el, callback);},10); // do the same check in 10 ms
}
};
var fixPosition = function($menu){ // correct the position of the menu in respect to #menuContainer
var h = $menu.outerHeight(true); // take the height of the menu
var menuBottom = $menu.offset().top + h - BASE_OFFSET; // the baseline of the menu (taking into consideration the BASE_OFFSET)
if(menuBottom > MAX_OFFSET){ // if this is outside the MAX height
var diff = MAX_OFFSET - menuBottom; // calculate the difference
var newTop = $menu.position().top + diff; // modify current positioning with the calculated diff value
$menu.css('top', newTop + 'px'); // apply it to top (which is also used by jquery to position submenus
}
$.fx.off = false; // switch animations back on
};
$( "#menu" ).menu().on('menufocus', function(ev, ui){ // on the event menufocus
var $ui = $(ui.item); //take the focused element
var $menu = $ui.children('ul'); // take its related submenu
if($menu.length === 0){ // if there is none
return; // just terminate
}
$.fx.off = true; // switch off jQuery effects (otherwise you'll have glitches)
whenVisible($menu, function(){fixPosition($menu);}); // execute fixPosition when $menu is visible
});
You could also look at the API for this widget:
http://api.jqueryui.com/menu/
You can use the position option to position the elements how you want.
This will change the position so that they are within the box, however you will want to dynamically access the last to give it the position you want as the code below will change all menu items to move up 50.
$( "#menu" ).menu({ position: { my: "left top", at: "right+5 top-50" } });
A complete list of positioning options are also found here: http://api.jqueryui.com/position/
Apparently jquery UI has accounted for this and has given the option "within" to make sure your element stays within another element of your choice.
Therefore Your solution should be this:
$( "#menu" ).menu({ position: {within: '#menuContainer' } });
I have a button back-to-top that is affixed to the left side of the screen - it uses scrollTop to slide-scroll to the top of the page when it's clicked. When the page the loads, the button is visible and does not cover anything that is readable etc.
When a user scrolls down the page, the button goes over certain DIVs that have text content. When the button goes into such a DIV I want it to hide using .hide(). Can't get it to work, here's what I have:
var p = $('a.back-to-top');
var position = p.position();
if(position == $('#about-me')){
$('a.back-to-top').hide();
}
Is if(position == $('#about-me')) the correct way to check if the button's position is in the #about-me DIV? Or, should I create a variable similar to position for the DIV?
EDIT: A messy but simple fiddle
You will need to do this check inside of a callback .. probably $(window).scroll so that it is checked each time the window scrolls; otherwise, it is only checked when the page loads.
I don't think you want to use position either as that is position relative to parent. Instead, you probably want .offset. This returns an object with top and left members. An == comparison does not make sense, especially to a jQuery object. You want to use:
$(window).on('scroll', function () {
var offset = $("a.back-to-top").offset().top;
var within = $("#about-me").offset().top;
if (offset >= within && offset <= within + $("#about-me").height()) {
$("a.back-to-top").hide();
}
else {
$("a.back-to-top").show();
}
});
The offset of .back-to-top changes with scrolling if it has a fixed position, but the offset of the static block does not change, so you can do this comparison.
See it in action: http://jsfiddle.net/QnhgF/
http://api.jquery.com/position/ - position() method returns a position object which has .left and .top properties. So basically, you can't compare position to some object returned by a selector. Instead, you should compare the "top" property values of both elements.
For example you have:
var p = $('a.back-to-top');
var position = p.position();
Also get this:
var aboutMePosition = $('#about-me').position();
And then you can compare:
aboutMePosition.top and position.top whichever way you need.