HTML fixed large element - javascript

I've been racking my brain and my Google Fu for a few hours now trying to find a solution to this one, but can't seem to come up with anything satisfactory.
I want to affix an element to the side of the page for some search criteria, much like Bootstrap's "Affix" plugin. (Demo Here). The problem is that it's going to be very common that the element is much taller than the window. So there will be scrolling of the element itself involved.
Usually this wouldn't be a problem because as the user hits the top + bottom of the document they would be able to see the top and bottom of the fixed element. (See bootstrap example while shrinking you're window very short). But we're planning on using infinite scroll on our results set, meaning there won't be a bottom to hit, and therefore they'll never see the bottom of the fixed element. As the user scrolls down, it needs to be bottom fixed so the user sees all criteria, then on the way up, it needs to be top fixed.
So I started off by modifying Bootstrap's plugin (I'm not actually using bootstrap). Now scrolling down the page is easy, using a fixed point on the bottom of the element means that it's not affixed until you reach the bottom of it.
But scrolling back up again is where I'm hitting issues.
Am I missing something really obvious and easy here (it is Monday morning after all), or does anyone know of a plugin / patch to bootstraps affix.
TL;DR
Need to affix a very tall element to the page and allow it to scroll. So it's fixed on the way down, then as they scroll back up, the element isn't fixed so it's also being scrolled up. Once the top of the element is hit, fix it there.

Is this what you Want to do DEMO
Simple jQuery function that will help.
$(function()
{
affix= $(".affix-top");
var affixHeight = parseInt(affix.height());
var affixTop = parseInt(affix.offset().top);
var affixBottom = parseInt(affixTop + affixHeight);
// Bind a scroll event for the whole page
$(document).bind("scroll", function(e)
{
// Calculate how far down the user has scrolled
var screenBottom = parseInt($(window).height() +$(window).scrollTop() );
// Test if the div has been revealed
if(screenBottom > affixBottom)
{
affix.attr("style","");
affix.css({"bottom":"0px","position":"fixed"});
}
else
{
affix.attr("style","");
affix.css({"top":"0px","position":"relative"});
}
});
});

Related

How to add child nodes to parent nodes without having view jump to where element is being loaded?

As I am rendering elements and appending them to a parent div, my screen keeps jumping to the bottom most element as it is being loaded rather than loading them and having the view stay at the current view. So at the beginning it should be at the top of the screen and stay there instead of jumping to the bottom and as I scroll down and it renders more elements it should stay at that spot as well whilst the rest loads.
Here is the code of what is essentially in my js file.
function loadMultipleElements(amountToLoad, url) {
var parentDiv = document.getElementById("instance");
for(var i = 0; i < amountToLoad; i++) {
var iframe = document.createElement('div')
iframe.innerHTML = '<iframe src=\"' + url + '\"></iframe>';
parentDiv.appendChild(iframe);
}
}
Then how I'm loading it in the html file with infinite scroll from jquery,
<script>
loadMultipleElements(5, "https://www.example.com");
$(window).scroll(function() {
if($(window).scrollTop() == ($(document).height()) - $(window).height()) {
loadMultipleElements(5, "https://www.example.com");
}
});
</script>
So when I run this on my localhost it will have everything render as it opens but jump to the bottom of the screen to render it then jump back to the current view. The big problem here is because of infinite scroll and how it keeps jumping to the bottom it ends up going indefinitely because it keeps jumping to the bottom triggering the jquery function.
EDIT: Plunker included though not sure how to get jquery to do infinite scrolling with plunker at the moment so right now just have a fixed load value of 10. Even already it is scrolling to the bottom as it renders more.
http://plnkr.co/edit/fUrJek3RAicHG98lUrC9?p=preview
Your problem is caused by the fact that when bing automatically focuses the search bar, your browser scrolls down to the iframe so that you can type in text.
(See a "slow-mo illustration" here.)
The only workaround I know of is to use the iframe sandbox attribute - HTML5 only! - to prevent bing from focusing the searchbar. Then when the iframe is finished loading, we reallow JavaScript. Example.
There are, however, a couple of problems with this approach.
Since it works by disabling javascript when the iframe is loading, desired javascript functionality is also disabled. (ie. no 'recent stories')
It feels incredibly hacky.
It isn't obvious what we're trying to do.
PS: Here's what W3Schools has to say about the sandbox attribute and here's a walkthrough on html5rocks.
PPS: If anyone knows of a better way to do this, I'd love to hear it.

Html, css, and jQuery. Something isnt working in my code

I'm new to jQuery and watching a tutorial for a sticky nav bar and something went wrong and idk what to do!
In my Script file I have it so it runs this code on load [http://pastebin.com/XYWR5tKJ][1] and I have a class in css to use with the nav Placeholder wrap.
Well the margin property doesn't seem to be working, if you run the site and scroll the whole way down the nav bar sticks to the side, its supposed to be centered(the margins job). I have no idea why its not doing it, its probably something stupid but please help!`
HERES THE CODE__
Script.js: http://pastebin.com/XYWR5tKJ
Css: http://pastebin.com/Y51rYJVE
HTML: http://pastebin.com/tTftEJKh
__
THANKS!
[1]: http://pastebin.com/tTftEJKh
Basic set up for a fixed, centered element is:
Containing element that is position fixed.
An element within that has margin:0 auto; and a set width.
I'd say that your left:0 inside fixed is counteracting things mostly.
Since you didn't specify responsive is this good enough for you?
http://jsbin.com/nevuqi/4/
Also probably better, as a tip to share code in something like a JSFiddle, Codepen or JSBin to name a few... good for learning inside of too.
This question reminded me of a JSFIDLE I made a while back to learn the same concept. I've updated it with comments to make it more readable...
It doesn't really answer your question but I thought it would help understand the various components involved when implementing the sticky nav effect in JQuery for anyone who comes across this thread who is unsure.
JavaScript/JQuery code:
(refer to jsfiddle for the accompanying html/css )
//window - the container that holds and renders the document.
//document - the rendered html within the window. the document can be bigger than the window as with this example as scrolling is needed..
//refer to css for more info on the appended classes to nav bar and proceeding element.
$(document).ready(function () {
//add a scroll function to the document that
$(document).on('scroll', function () {
//get the number of pixels that the window is from the top of the document. this is zero at first.
var scrollTop = $(this).scrollTop();
//insert the name of your sticky nav element here in place of .scrollFixed
$('.scrollFixed').each(function () {
//scrollFix variable is initialized as .scrollFixed object with all its attributes.
var scrollFix = $(this);
//gets offset of sticky nav element in pixels
var topDistance = scrollFix.offset().top;
var previousElement = scrollFix.prev();
//this is just for debugging and learning purposes.
$('.fixed_info').html('nav bar is ' + topDistance + ' pixels from top of document');
//if you put topDistance here instead of the number manually, the nav bar will flicker.
//unsure why..
//checks to see whether nav element has been scrolled past the top of window.
if ((298) < scrollTop) {
//make sticky nav a fixed element
scrollFix.addClass("stuck");
//extend the element below for this example so proceeding elements don't visually jump up
//when closing the empty gap.
$(".element_below_fixed_nav_bar").addClass("extend");
//indicates element is fixed!
scrollFix.html("Element now fixed!");
//you will have to manually put the topDistance here as well...
//this checks whether the nav element's original top has passed the top of
//the enclosing window.
//it needs to become scrollable again
} else if (298 >= scrollTop && scrollFix.hasClass('stuck')) {
//make sticky nav a scrollable element
scrollFix.removeClass('stuck');
//make proceeding element shorter to compensate for sticky nav pushing elements below it down.
$(".element_below_fixed_nav_bar").removeClass("extend");
//indicates element is scrollable!
scrollFix.html("Element now moveable!");
}
});
});
});
It's very similar to the logic behind the JavaScript code you linked.
find number of pixels of window from top of document. starts at 0 when document first loads unless otherwise coded. This updates every time you scroll.
find (offset) number of pixels of nav bar element from top of document.
check if nav bar has reached the top of the window by checking its offset to the window. If it is then make it fixed.
check whether the nav bar's original offset has fallen below the top of the window. If it has then make the nav bar scrollable.
It doesn't really answer your question but I thought it would help understand the various components involved when implementing the sticky nav effect in JQuery for anyone who comes across this thread who is unsure.

jQuery scrolling out of view issue

I am working on building a schedule. So far it's pretty straight-forward. There is one bit of functionality I am having issues with.
I have an ul that has a fixed height to allow scrolling. There are "Labels" (li.dayLabel) withing the ul that separate the hours. What I am trying to do is to have it so that when a label is scrolled out of view it will change the text in the placeholder to it's text. Then once that works, I need it to work in reverse. So when they label scrolls back into view it updates the placeholder. Basically, I am trying to make the placeholder be a title for the available items until another label is then scrolled out of view. This is for scrolling from the top. So as you scroll down the list the placeholder is meant to be a title for the section you are viewing until you reach another section and it takes its place. Then when you scroll back down I need it to replace the text with the previous li.dayLabel so the sections stay organized. I hope this makes sense.
You can see what I am trying to do by looking at the original that I am basing this off of. Notice how the placeholder changes as you scroll down the list and changes back when you scroll back up.
Demo: jsFiddle // Note: line 54 is the part that is in question
I originally used:
$(".snlf-schedule-list li.dayLabel:visible:first").text();
as the :first selector is suppose to only match a single element.
I later tried:
$(".snlf-schedule-list li.dayLabel:visible").filter(":eq(0)")
as this is suppose to be the same thing.
It seems that when an element is out of view it still is considered :visible I believe this is my issue.
Am I doing this completely wrong? I was under the impression that when you scroll an element like this it should no longer be :visible. After reading the documentation I have learned that this is not the correct selector to use.
It would appear that scrollTop is how I should be doing this. Now I have used scrollTop for scrolling down pages to disable animations when not in view but I am not clear on how to untilize this for a ul with scrollbars.
I tried:
var _first = $('li.dayLabel:first'); // next element to scroll out of view?
if( $(this).scrollTop() > (_first.offset().top+_first.height())) {
// Out of view
console.log("out");
} else {
// in view
console.log("in");
}
Updated Demo: jsFiddle
But it seems to be redundant as it's already calculating the first element so I am not sure how to get the correct element (the next one that's about to scroll out of view.) Then I need this to work when they scroll back up...
Any insight on this is much appreciated. Hopefully it's something simple I am just over complicating or missing completely.
Thanks,
Jeremy
The solution for my case was:
// Set placeholder text on scroll
var _scrollCagePositionTop = $(".snlf-schedule-list").offset().top;
var _first = $('li.dayLabel:first'); // first dayLabel element
$(".snlf-schedule-list").scroll(function(){
var _lastOffText = $(_first).text();
$("li.dayLabel").each(function() {
if ($(this).offset().top < _scrollCagePositionTop) {
_lastOffText = $(this).text();
}
});
$("#schedule-placeholder").text(_lastOffText);
});
What I did was set the known position of the top of the scroll cage (_scrollCagePositionTop)
When the user scrolls I set a variable _lastOffText that keeps track of the last item text content when scrolled out of view (less offset top than the palceholder). I then set this value to the placeholder.
This method allows me to have the proper text in my placeholder when the user scrolls up or down.
To fix the issue of an empty placeholder when the user scrolls back to the top I just set the default of _lastOffText to be the text of the first label ($(_first).text())
Hope others find this useful.
Here is the working demo: jsFiddle Final

Is it possible to keep (auto) scrolling even when there's nothing left?

I am developing a web app which runs on a (windows) tablet. I won't go into too much detail, but basically the user has a list of tasks and checks each one off when it's done.
When they check a task, I use jQuery (scrollTop()) to scroll so that they can click in the same place for the next task, instead of having to manually scroll (which is tricky on this particular tablet).
The problem is, that when they can to the last 5 or 6 tasks, it's the end of the div, so the scrolling stops, which is weird because they have been used to clicking in the same place.
I would like to keep it scrolling, but I am not sure how to.
My guess is just to add whitespace at the bottom, but then I am not sure how to detect when it's reached the bottom in order to add the whitespace.
On page load find the last list item. Then add whitespace so that it can scroll to the top of the page. I do this for one of my websites so that when people visit anchors, they appear at the top of the page. Hate it when they don't myself!
var $lastinput = $('input').last();
if ($lastinput.length > 0) {
var headerTop = $lastinput.offset().top;
var spacing = $(window).height() - ($('body').height() - headerTop);
$('#setpageheight').height(spacing);
}
At the bottom of the content area I have a zero height div called setpageheight. I give this a height as necessary.
http://jsfiddle.net/Ge7nM/

How to make an element slide with the viewport as it scrolls?

I've Googled for this but must be using the wrong keywords.
Basically I want to use the effect that Magento and now Stack Overflow uses. That is, there is an element in a column, and when you scroll down, it sticks to the top of the viewport. And once scrolled up again, it goes back into the normal page flow.
This Ask A Question is a good page for example. Scroll down and watch the "How to Format" element come down (might need to make your viewport smaller if you have a large screen to see the effect).
I've noticed it is setting position: fixed in the CSS. The JavaScript however is obfuscated.
What's the easiest way to achieve this effect? Is there a jQuery plugin available?
Here is an article that should help: http://www.wduffy.co.uk/blog/keep-element-in-view-while-scrolling-using-jquery/comment-page-1/
I noticed google doing this in certain places, like here http://news.google.com/nwshp?hl=en (the left side navigation bar). From what I can tell, they checking the position on the page and then setting the item to a fixed position once the page is scrolled down enough for the element to start scrolling off the screen.
It looks like the other method, using jQuery to set the top margin will allow the element to lag behind and get choppy (if you don't use animation) since the javascript must continue to position the element.
Here is an example in Ext, it would probably help a lot if I didn't have the select in the event handler, but it works.
Ext.fly(document).on("scroll", function(e,t,o){
Ext.select(".pinnable").each(function(el,c,idx){
var y = window.scrollY;
if(!el.hasClass("pinned")){
var ypos = el.getY();
if(y>ypos){
el.addClass("pinned");
el.set({
originalY:ypos
});
}
} else {
var origy = el.getAttribute("originalY");
if(origy && y<origy){
el.removeClass("pinned")
}
}
});
});

Categories