Why isn't this lining up right with jQuery? - javascript

I needed to put in a flyout menu real quick for a client. I didn't want to mess with the CSS or HTML as they have it styled without JS exactly how they want it and they just want me to add the JS. I just thought it'd be simple to set the inner <ul> to position absolute and then the top offset to be the top of the parent <li> but it's not working at all. not even close.
$(function(){
$('#snav-links > li > ul').css({
display:'none',
position:'absolute',
background:'#00182E',
left:$('#snav-links').width()+'px'
})
.parent().hover(
function(){
$(this).find('ul').css({display:'block',top:$(this).offset().top+'px'})
},
function(){
$(this).find('ul').css({display:'none'})
}
);
});
Here is the page: http://www.nwcidisplays.com/_temp/
Hover over the left sidebar menu items Banner Stands and Truss Displays. You'll see how off it is. Im not sure how to fix it. Ideas?

The culprit of you troubles is the anchors within #snav-links > li. They are floating and don't take up space withing the li-element. This will lead the li element to have the minimal height and they are positioned way above the actual link.
Remove the float and set the parent to relative positioning and that's it: http://jsfiddle.net/rEVwd/6/.
You'll also have to tweak the margin or padding in the li-elements so that the end result will be the same as before.

If you set position of #snav-links > li element to relative then the nested absolute ul will be relative to that container.
So (top 0, left 0) for your ul will be the top corner of the LI.
$('#snav-links > li').css({
position:'relative', // magic here
}.find(' > ul').css({
display:'none',
position:'absolute',
background:'#00182E',
top:0,
left:$('#snav-links').width()+'px'
}).end() // end() will take to back to the last selector (ie. $('#snav-links > li'))
.hover(
function(){
$(this).find('ul').css({display:'block'})
},
function(){
$(this).find('ul').css({display:'none'})
}
);
You might then need to adjust the top and left based on that menu size (i'm not sure how your menu looks like)

If you inspect with FireBug the parent li is positioned quite a bit above the button. (As Aleksi said, due to it being a floated element) (The button shows up as a.slink, it's parent li is located above it) So when you're retrieving the offset of the li, you're getting that location.
So you could try using the a.slink instead as it's positioned where you want it.
Also, to position the left directly next to the button, you'll need the offset + width of #snav-links
$(function(){
$('#snav-links > li > ul').css({
display:'none',
position:'absolute',
background:'#00182E',
left:$('#snav-links').offset().left + $('#snav-links').outerWidth()+'px'
})
.parent().hover(
function(){
$(this).find('ul').css({display:'block',top:$(this).find('a').offset().top+'px'})
},
function(){
$(this).find('ul').css({display:'none'})
}
);
});

Related

Using Jquery to toggle on and off items based distance to top

I am creating a site in which there are a number of fixed background images that you scroll past. Associated with each fixed background is an image slider (or text) that is hidden until the title is clicked on. These items are all fixed positioned.
I was able to make this work by using z-index to place items in order top to bottom/first to last and then have each disappear in turn using:
$(document).scroll(function() {
$('#porttitle').toggle($(this).scrollTop() < 225);
});
However, I am unable to use this because the length pixel distance down on the page changes based on the screen size. I am pretty new to Jquery but wanted to try to use .offset .top to have the item disappear not based on the pixel length to the top of the page but instead when an element appears on the screen. This is what I have so far but it isn't seeming to work.
$(document).scroll(function() {
$('#porttitle').toggle($(this).scrollTop() < $(‘article.post-100’).offset().top);
});
Here is the link to the site: http://s416809079.onlinehome.us (not final location - just developing)
Any thoughts?
Thanks!
I think this may work for you, read the comments on the code for a line by line explanation.
Working Example
$(window).scroll(function () { // When the user scrolls
$('div').each(function () { // check each div
if ($(window).scrollTop() < $(this).offset().top) { // if the window has been scrolled beyond the top of the div
$(this).css('opacity', '1'); //change the opacity to 1
} else { // if not
$(this).css('opacity', '0'); // change the opacity to 0
}
});
});
I'm conditionally changing the opacity rather than using toggle because:
...jQuery does not support getting the offset coordinates of hidden
elements or accounting for borders, margins, or padding set on the
body element.
While it is possible to get the coordinates of elements with
visibility:hidden set, display:none is excluded from the rendering
tree and thus has a position that is undefined.
Related documentation:
.offset()
.each()
.scroll()
.scrollTop()

How to make links selected when scrolling?

I am having a trouble on adding a jquery code to a landing page so that when I scroll down among the sections the relevant sections should be shown in the navbar links by adding a class named clicked. I have added the code snippet that I am currently working on for your reference.. :-)
Any help would be gladly appreciated. :-)
$(document).ready(function(){
$(".link").click(function(event){
------ Scroll code ------------
$(".clicked").removeClass("clicked");
$(event.target).addClass("clicked");
});
});
You don't need to add an onClick event handler for that. The approach you should be using is not that difficult.
First you need to know your current scrolling position, which you can retrieve using:
$(document).scrollTop();
Then you need to know the position of bottom of the visible portion, which is actually the scrolling position + the height of the window:
var btm = $(this).scrollTop() + $(window).height();
Now we need to check if the section is above the bottom portion (that means it's visible), so in order to do that we need to get the position of the section. You can do that by using:
var titlePos = $($(myLink).attr("href")).offset().top;
What happens here is that we're going to look for the section that is referred to by the navbar link and then get it's offset (that's the position of where it's located on the document). You get both the left and top offset, but in this case we only need to get the top offset.
The only thing you need to do know is automate this for all links in your navigation, you can do that for example by doing:
$(".nav li a").each(function() {
var titlePos = $($(this).attr("href")).offset().top;
});
The next step is that we're going to look if the position of the title is above the bottom of the screen, that means that that section is/was visible. You can do that by using:
var btm = $(this).scrollTop() + $(window).height();
$(".nav li a").each(function() {
var titlePos = $($(this).attr("href")).offset().top;
if (titlePos < btm) {
$(this).addClass("visited");
}
});
Now there is only one problem. Sections that are above the screen (= sections you already passed/read) are also above the bottom of the screen, which means that with this code they will be active as well.
To fix that, we need to remove the .visited class from the previous link the moment we know that the next section is visible. You can do that by using:
$(this).parents("li").prev().children("a").removeClass("visited");
This goes to the link just before the link that's active and remove the .visited class from it, so actually only the last visible section is marked as visible.
Now you just add all of this to a scroll event handler and trigger it once to initialize the navigation. The code would become something like:
$(this).scroll(function() {
var btm = $(this).scrollTop() + $(window).height();
$(".nav li a").removeClass("visited").each(function() {
var titlePos = $($(this).attr("href")).offset().top;
if (titlePos < btm) {
$(this).addClass("visited");
$(this).parents("li").prev().children("a")
.removeClass("visited");
}
});
}).trigger("scroll");
Also notice the small change, when I scroll, I first remove the .visited class from all navigation links. I also made a JSFiddle demonstrating this.

Position fixed acting like position relative ( scrolling with page )

I'm styling an element with position fixed and other css in a certain condition ( basically if the user scrolls up ), but the element is behaving like a relative positioned element. In other words, it is scrolling with the page and not remaining fixed.
I tried isolating this issue, but this issue only exists in this site as a whole and I need it to work in this site.
var lastScrollTop = 0;
$(window).scroll(function(){
var st = $(this).scrollTop();
if(st<=lastScrollTop){
//scroll up
if($(this).scrollTop()>235) $('#searchInput').removeClass('slideIn').addClass('stickySearch');
else $('#searchInput').removeClass('stickySearch').addClass('slideIn');
}
else $('#searchInput').removeClass('stickySearch').removeClass('slideIn');
lastScrollTop = st;
});
Right now the class .slideIn has no styling associated with it, but .stickySearch does.
Here is the CSS:
.stickySearch{
width:56% !important;
position:fixed !important;
left:0;
right:0;
}
I checked in developer tools and the class is being applied and the styles are being applied, but the position fixed is just not working.
Here is a live URL: http://goo.gl/ns6UEQ
Note, it helps to have a small window in height so you can scroll. Scroll down so that the header is hidden up top and then scroll up and the search bar should appear, but the moment the header comes back into view the search bar will go back into place in the header.
This is a bug that exists in CSS and in Chrome and Firefox's implementation of CSS.
When you have a parent element that has backface-visibility or is transformed, its children can not be fixed.
More here: http://www.sitepoint.com/forums/showthread.php?1129352-CSS3-tip-of-the-week-No-1&highlight=chrome+bug+fixed
Solution: remove the transform and backface visibility styling from #container
Change the if statement to something like below
var lastScrollTop=0;
$(window).scroll(function(){
if($(this).scrollTop()>150 && lastScrollTop>$(this).scrollTop()){
$('#fixedinput').addClass('fixed');
} else {
$('#fixedinput').removeClass('fixed');
}
lastScrollTop=$(this).scrollTop();
});
JSFiddle demo
As you scroll down past the grey part the will not be fixed, but once you start scrolling up it will.

How can I tell with javascript if some dom nodes float: left or they go down to a new line?

I encountered some dom nodes which float: left like the main grid of movies on this page, http://trailers.apple.com/. The main grid is made up of ul li ... with many li items.
Each li item float's left, as the CSS is:
#trailers li {
float: left; ...
How can I tell from Javascript if a html dom element floats left or it goes down to a new line?
You can check this using jQuery by running a function which iterates over all list items and checks a li's top offset value compared to the top offset value of its previous sibling. Here's some jQuery which does this, it skips over the first li (as it doesn't have a previous sibling) and sets a red background on each li which has a top offset value higher than the top offset value of its previous sibling.
$("li").each(function () {
if (!$(this).is("li:first-child")) {
if ($(this).offset().top > $(this).prev().offset().top) {
$(this).css('background-color', 'red');
}
}
});
Here's a jsFiddle showing how this would work. You would have to run this again after resizing the container. Here's a jsFiddle showing what happens when the list items have different heights. It still works unless you define "new line" as "starting at the left side of the container". In that case you could instead check the left offset value.
$("li").each(function () {
if ($(this).offset().left < 100) {
$(this).css('background-color', 'red');
}
});
* 100 is the width of the li here, it can be any value lower than the left offset value of the second li on the line.
Here's a jsFiddle showing this approach.

jQuery scrolling UL with hidden overflow

I have a UL with LI's set to display horizontally. The UL has a fixed width and it's set to hide the overflow. This is so I can display my images, which are to be used in a gallery, neatly. It works and looks nice.
I want to, however, use jQuery to scroll the contents of the UL rather than set the overflow property to auto and be presented with those ugly scroll bars. I recycled some code I used to do the same thing a few weeks back but, back then, I was doing it in DIV's. Much easier, apparently.
$('.gallery_container span').hover(
function()
{
if ($(this).attr('class') == 'up')
direction = '-=';
else
direction = '+=';
var divOffset = $('ul.gallery').offset().top;
$('ul.gallery').animate({scrollTop: direction + divOffset}, 5000);
},
function()
{
$('ul.gallery').stop();
});
I saw a site that says the scrollTop property can be applied to UL's. So I'm not sure what exactly is causing this not to work.
Any ideas?
EDIT: Found what was causing it to not work at all but not it scrolls vertically - Kind of expected that. Is there any way to scroll it horizontally?
Perhaps:
$('ul.gallery').animate({scrollLeft: direction + divOffset},2000);

Categories

Resources