JQuery - Responsive Navigation on tab Overflow using cookies and Window width - javascript

here is an interesting question.
I have a navigation bar that looks like this:
< div id = "main_nav" >
< ul >
< li id = "Tab1" > Home < / li >
< li id = "Tab2" > Home1 < / li >
< li id = "Tab3" > Home2 < / li >
< li id = "etc" > etc etc < / li >
...
< / ul >
< / div >
So the #main_nav has fixed width of 980px with overflow hidden and tabs are inline block.
When the screen width decreased in size, the tabs are overflowing and are beyond the screen view, thous are hidden.
To make it fun, I created a property to catch the last tab and see if it is overflowing, if it does, fire the event so the tab changes the from block to something else like responsive design.
Here is the code:
$( window ).on( 'resize', function(){ resize(); } );
function resize() {
var pageWidth = $ ( "#main_nav" ).width();
var elementWidth = $ ( "#tab14" ).width();
var elementLeft = $ ( "#tab14" ).position().left;
if ( pageWidth - ( elementWidth + elementLeft ) < 0 ) {
$ ( 'ul > li' ) .css ( { 'float': 'left' } );
}
else {
$ ( 'ul > li' ) .css ( { 'float': '' } );
}
}
The problem: The tabs starts flickering as it checks if #tab14 is overflown and on refresh you need to resize window to get to that state.
The question:
1. Not related to the issue but, what is a good Jquery counter to find the number of the last tab automatically and fill in to the $("#tab NUMBER?").width();
To avoid flickering, I tried the Timer, none worked. Do any of you know how to Save a Cookie of the Screen Width when the Tab event (tab overflowing) fired? So I can fire the else event only after that screen width reached to return tab to its original shape.
Your input is very appreciated! Thank you.

You can save cookies in JavaScript by using the window.localStorage method. Take a look at https://developer.mozilla.org/en/docs/Web/Guide/API/DOM/Storage for more information.

Thank you all, here is my own solution:
Responsive Navigation on Overflow:
$(window).on('resize', function(){
ress_nav();
});
function more_nav() {
$('#main_nav li').css({'width': ''});
$('#main_nav li').css({'float': ''});
}
function less_nav() {
$('#main_nav li').css({'width': '50%'});
$('#main_nav li').css({'float': 'left'});
}
function ress_nav() {
var lastTab = $("#main_nav li:last-child");
var winWidth = $(window).width();
var elWidth = $(lastTab).width();
var elLeft = $(lastTab).position().left;
if (winWidth - (elWidth + elLeft) < 0) {
$.cookie('winWidth', winWidth);
less_nav();
}
else if ($(window).width() > $.cookie('winWidth')){
$.removeCookie('winWidth', winWidth);
more_nav();
}
}
if ($(window).width() > $.cookie('winWidth')) {more_nav()} else {less_nav()}
Hope it helps anyone looking for such a function.
Thank you.

Related

How to check if div reaches top of page for each div?

This is my current solution to check if a specific div reaches the top of the page, which i got from here https://stackoverflow.com/a/5279537/4671165
document.addEventListener("scroll", Scroll, false);
function Scroll() {
var top = $('.element').offset().top - $(document).scrollTop();
if (top < 150){
var textvariable = $('.text').text();
}
}
But i want this to do something each time a different div reaches the top of the page, therefore i currently have
var top1 = $('.element1').offset().top - $(document).scrollTop();
var top2 = $('.element2').offset().top - $(document).scrollTop();
var top3 = $('.element3').offset().top - $(document).scrollTop();
if (top1 < 150 && top2 > 150){
var textvariable = $('.text1').text();
}
if (top1 < 150 && top2 < 150 && top3 > 250){
var textvariable = $(.text2').text();
}
if (top2 < 150 && top3 < 250){
var textvariable = $(.text3').text();
}
However, this doesn't seem the most effective way but i can't figure out what is. Especially since i have more elements then just 3 in the project. So i am looking for a more effective way.
I put this together using ES6. I believe this should work. It's been a while since I've used getBoundingClientRect() though.
var divs = document.querySelectAll('div');
document.addEventListener("scroll", Scroll, false);
function Scroll() {
divs.forEach((memo,index) => {
let divTop = memo.getBoundingClientRect().top;
if (divTop <= 0) {
var textvariable = $('.text' + index).text();
});
}
Hope this helps. It should be easier to use and it has a lot of bugs already fixed for you. It's a 1.82 kb file so there's not really much useless stuff into it if added.
I found a jquery solution
function ScrollStart() {
var scrolled = $(this).scrollTop();
/*filter current element at the top with a certain class & give it active class*/
$('.step').removeClass('activetext').filter(function() {
return scrolled <= $(this).offset().top + $(this).height() - 50 && scrolled >= $(this).offset().top - 50;
}).addClass('activetext');
/* make exclusion for first element */
var boven = $('.first').offset().top - $(document).scrollTop();
if (boven > 0){
$('.first').addClass('activetext');
}
/*make exclusion for last element*/
var bottom = $('.last').offset().top - ($('.last').height()/5) - $(document).scrollTop();
if (bottom < 150){
$('.step').removeClass('activetext')
$('.last').addClass('activetext');
}
else{
$('.last').removeClass('activetext')
}
/* give variable 'text' the text of the active class & append it */
var text = $('.activetext .headertekst').text();
$('.dropbtn').empty();
$('.dropbtn').append(text);
$('.dropbtn').append('<img src="images/downarrow.svg" galleryimg="no"></img>');
}

Only execute JS if the screen size is more than 1024px?

I have a sidebar that becomes position:fixed when the bottom of the div is visible (followed this tutorial). My problem is I only need the JS to work if the screen size is more than or equal to 1025px.
I know I need something along the lines of if($(window).width() > 1025), but I can't figure out where that needs to be. I'm not great with JS so any help would be appreciated.
Demo
JS
$(function () {
if ($('.leftsidebar').offset()!=null) {
var top = $('.leftsidebar').offset().top - parseFloat($('.leftsidebar').css('margin-top').replace(/auto/, 0));
var height = $('.leftsidebar').height();
var winHeight = $(window).height();
var footerTop = $('#footer').offset().top - parseFloat($('#footer').css('margin-top').replace(/auto/, 0));
var gap = 100;
$(window).scroll(function (event) {
// what the y position of the scroll is
var y = $(this).scrollTop();
// whether that's below the form
if (y+winHeight >= top+ height+gap && y+winHeight<=footerTop) {
// if so, ad the fixed class
$('.leftsidebar').addClass('leftsidebarfixed').css('top',winHeight-height-gap +'px');
}
else if (y+winHeight>footerTop) {
// if so, add the fixed class
$('.leftsidebar').addClass('leftsidebarfixed').css('top',footerTop-height-y-gap+'px');
}
else
{
// otherwise remove it
$('.leftsidebar').removeClass('leftsidebarfixed').css('top','315px');
}
});
}
}
This should work:
var flag = false;
// This will keep on checking for window size while you are scrolling.
$(window).on("scroll", function() {
if (flag){
// Do whatever you want here
alert("hey");
}
});
$(window).on("resize", function() {
if ($(window).width() >= 1025){
flag = true;
} else {
flag = false;
}
})
From my comment: Just put that if($(window).width() > 1025) inside the function provided to the scroll event.
e.g.
$(window).scroll(function (event) {
if ($(window).width() > 1024) {
// what the y position of the scroll is
var y = $(this).scrollTop();
// whether that's below the form
if (y + winHeight >= top + height + gap && y + winHeight <= footerTop) {
// if so, ad the fixed class
$('.leftsidebar').addClass('leftsidebarfixed').css('top', winHeight - height - gap + 'px');
} else if (y + winHeight > footerTop) {
// if so, ad the fixed class
$('.leftsidebar').addClass('leftsidebarfixed').css('top', footerTop - height - y - gap + 'px');
JSFiddle: http://jsfiddle.net/TrueBlueAussie/3w5dt/31/
Notes:
not that 1 PX matters, but you did say > 1024px, hence changing 1025 to 1024 :)
First of all you should have a look at the jQuery documentation. The $.browser function was removed in jQuery 1.9. This can end up in serious problems in your code.
Just add something like the follwing code in the first if condition:
if (!msie6 && $('.leftsidebar').offset()!=null && $(window).width() > 1025 ) {
...
}
That should be all. If you want, that javascript should react on window resize just add something like the following
$(window).on('resize', function( event ) { /* code here */ }).trigger('resize');
if(screen.width >= 1024)
{
$(window).scroll(function (event) {
//Write your function code here
});
}
I hope it will help you.

Getting a floating div to stop upon reaching another div

I have a floating div on the sidebar that scrolls with the page. Is there a way to add code that makes it stop when it reaches the footer?
See code in action: http://openbayou.staging.wpengine.com
jQuery code used to float div:
$j=jQuery.noConflict();
$j(document).ready(function($) {
//this is the floating content
var $floatingbox = $('#one');
if($('#primary').length > 0){
var bodyY = parseInt($('#primary').offset().top) - 20;
var originalX = $floatingbox.css('margin-left');
$(window).scroll(function () {
var scrollY = $(window).scrollTop();
var isfixed = $floatingbox.css('position') == 'fixed';
if($floatingbox.length > 0){
$floatingbox.html();
if ( scrollY > 1561 && !isfixed ) {
$floatingbox.stop().css({
position: 'fixed',
top: 10,
});
} else if ( scrollY < 1561 && isfixed ) {
$floatingbox.css({
position: 'relative',
top: 0,
});
}
}
});
}
});
Why not just set the z-index of the sidebar behind the z-index of the footer?
EDIT: I didn't like the result of this so I went and made this work in jquery the way you want it...
try this for your scroll function:
$(window).scroll(function () {
floatingbox = $("#one");
if(floatingbox.length > 0){
//get our current scroll position
var scrollY = $(window).scrollTop();
//get the position of the tag cloud relative to the document
var contentY = ($("#sidebar .sidebar-tag-cloud").offset().top + $("#sidebar .sidebar-tag-cloud").outerHeight(false));
//calculate the largest possible top margin size before it starts to overlap the footer
var lastY = $("#footer").offset().top - $("#one").outerHeight(false);
//check if our scroll location is past the bottom of the tag cloud
if ( scrollY > contentY )
{
//check if the current top position is less than the maximum position
if(floatingbox.offset().top<lastY)
{
//keep scrolling
floatingbox.stop().animate({"marginTop":scrollY-contentY});
}else
{
//check if we have scrolled back up and have a space at the top
if(scrollY<floatingbox.offset().top)
{
floatingbox.stop().animate({"marginTop":scrollY-contentY});
}else
{
// hard set to the maximum position
floatingbox.stop().css({"marginTop":lastY-contentY});
}
}
}
}
});
I also made it a little more dynamic by getting the location of the bottom of the tag cloud and using that instead of your hard-coded number.
Alright, after looking at your latest jsfiddle. I have modified that code to work with yours. http://jsfiddle.net/Tgm6Y/4430/ This will not have the animate lag and should work well for you.
$('#one').followTo('#two','#pointFive');
just replace #two with #footer and #pointFive with "#sidebar .sidebar-tag-cloud" and this should work in your code.
UPDATE: Found a solution to my problem.
$(function () {
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6) {
var top = $('#one').offset().top;
$(window).scroll(function (event) {
var y = $(this).scrollTop() + 20;
if (y >= top) {
$('#one').addClass('fixed');
}
else {
$('#one').removeClass('fixed');
}
// don't overlap the footer - pull sidebar up using a negative margin
footertotop = ($('#footer').position().top);
scrolltop = $(document).scrollTop() + 760;
difference = scrolltop - footertotop;
if (scrolltop > footertotop) {
$('#one').css('margin-top', 0 - difference);
}
else {
$('#one').css('margin-top', 0);
}
});
}
});
What this does is it stops before the footer and I can configure the stopping point.
I appreciate all the help in solving my problem!

run javascript on div click?

i wonder if someone can help, basically i have this javascript which fades in a div when the user scrolls down a page, however, i want to put a condition on the javascript to say only fade after the user has clicked another div element.
for instance i need the user to read a piece of text before they scroll down the page and this div fades in, on this piece of text is a div called
so once the user has read the text they will click 'exit_profile_intro4' which will close the text box,
only then do i want the javascript for the scroll and fade in div to work. can someone please show me how i can do this: i've tried
<script>
$('div.exit_intro4').click(function(){
$(window).scroll(function(){
var leftToBottom = $(document).height() - $(window).height() - $(window).scrollTop();
var distanceFromTop = $(window).scrollTop();
if( distanceFromTop > 300 && !$("profile_intro_case5").is(":visible")
&& leftToBottom > 1000 && !$(".profile_intro_case5").is(":animated")) {
$(".profile_intro_case5").fadeIn(1000);
}else if($(".profile_intro_case5").is(":visible") && (distanceFromTop < 300 || leftToBottom < 1000) && !$(".profile_intro_case5").is(":animated")){
$(".profile_intro_case5").fadeOut();
}
});
});
</script>
original:
<script>
$(window).scroll(function(){
var leftToBottom = $(document).height() - $(window).height() - $(window).scrollTop();
var distanceFromTop = $(window).scrollTop();
if( distanceFromTop > 300 && !$("profile_intro_case5").is(":visible")
&& leftToBottom > 1000 && !$(".profile_intro_case5").is(":animated")) {
$(".profile_intro_case5").fadeIn(1000);
}else if($(".profile_intro_case5").is(":visible") && (distanceFromTop < 300 || leftToBottom < 1000) && !$(".profile_intro_case5").is(":animated")){
$(".profile_intro_case5").fadeOut();
}
});
</script>
Add a state to the scroll event.
(function() {
var user_can_scroll = false;
$("div.exit_intro4").click(function(e) {
/* do your thing */
user_can_scroll = true;
});
$(window).scroll(function(e) {
if (user_can_scroll) {
/* do your scroll thing */
}
});
})();
I see no reason why your code would be incorrect (without actually running it), however you assign a click like this
$('div.exit_intro4').click( // Function
Yet, you say you want to trigger it when "exit_profile_intro4" is clicked. Perhaps it should be this.
$('div.exit_profile_intro4').click( // Function

Scrolling child div scrolls the window, how do I stop that?

I have a div, with a scroll bar, When it reaches the end, my page starts scrolling. Is there anyway I can stop this behavior ?
You can inactivate the scrolling of the whole page by doing something like this:
<div onmouseover="document.body.style.overflow='hidden';" onmouseout="document.body.style.overflow='auto';"></div>
Found the solution.
http://jsbin.com/itajok
This is what I needed.
And this is the code.
http://jsbin.com/itajok/edit#javascript,html
Uses a jQuery Plug-in.
Update due to deprecation notice
From jquery-mousewheel:
The old behavior of adding three arguments (delta, deltaX, and deltaY)
to the event handler is now deprecated and will be removed in later
releases.
Then, event.deltaY must now be used:
var toolbox = $('#toolbox'),
height = toolbox.height(),
scrollHeight = toolbox.get(0).scrollHeight;
toolbox.off("mousewheel").on("mousewheel", function (event) {
var blockScrolling = this.scrollTop === scrollHeight - height && event.deltaY < 0 || this.scrollTop === 0 && event.deltaY > 0;
return !blockScrolling;
});
Demo
The selected solution is a work of art. Thought it was worthy of a plugin....
$.fn.scrollGuard = function() {
return this
.on( 'wheel', function ( e ) {
var event = e.originalEvent;
var d = event.wheelDelta || -event.detail;
this.scrollTop += ( d < 0 ? 1 : -1 ) * 30;
e.preventDefault();
});
};
This has been an ongoing inconvenience for me and this solution is so clean compared to other hacks I've seen. Curious to know how more about how it works and how widely supported it would be, but cheers to Jeevan and whoever originally came up with this. BTW - stackoverflow answer editor needs this!
UPDATE
I believe this is better in that it doesn't try to manipulate the DOM at all, only prevents bubbling conditionally...
$.fn.scrollGuard2 = function() {
return this
.on( 'wheel', function ( e ) {
var $this = $(this);
if (e.originalEvent.deltaY < 0) {
/* scrolling up */
return ($this.scrollTop() > 0);
} else {
/* scrolling down */
return ($this.scrollTop() + $this.innerHeight() < $this[0].scrollHeight);
}
})
;
};
Works great in chrome and much simpler than other solutions... let me know how it fares elsewhere...
FIDDLE
You could use a mouseover event on the div to disable the body scrollbar and then a mouseout event to activate it again?
E.g. The HTML
<div onmouseover="disableBodyScroll();" onmouseout="enableBodyScroll();">
content
</div>
And then the javascript like so:
var body = document.getElementsByTagName('body')[0];
function disableBodyScroll() {
body.style.overflowY = 'hidden';
}
function enableBodyScroll() {
body.style.overflowY = 'auto';
}
As answered here, most modern browsers now support the overscroll-behavior: none; CSS property, that prevents scroll chaining. And that's it, just one line!
Here's a cross-browser way to do this on the Y axis, it works on desktop and mobile. Tested on OSX and iOS.
var scrollArea = this.querySelector(".scroll-area");
scrollArea.addEventListener("wheel", function() {
var scrollTop = this.scrollTop;
var maxScroll = this.scrollHeight - this.offsetHeight;
var deltaY = event.deltaY;
if ( (scrollTop >= maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
event.preventDefault();
}
}, {passive:false});
scrollArea.addEventListener("touchstart", function(event) {
this.previousClientY = event.touches[0].clientY;
}, {passive:false});
scrollArea.addEventListener("touchmove", function(event) {
var scrollTop = this.scrollTop;
var maxScroll = this.scrollHeight - this.offsetHeight;
var currentClientY = event.touches[0].clientY;
var deltaY = this.previousClientY - currentClientY;
if ( (scrollTop >= maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
event.preventDefault();
}
this.previousClientY = currentClientY;
}, {passive:false});
I wrote resolving for this issue
var div;
div = document.getElementsByClassName('selector')[0];
div.addEventListener('mousewheel', function(e) {
if (div.clientHeight + div.scrollTop + e.deltaY >= div.scrollHeight) {
e.preventDefault();
div.scrollTop = div.scrollHeight;
} else if (div.scrollTop + e.deltaY <= 0) {
e.preventDefault();
div.scrollTop = 0;
}
}, false);
If I understand your question correctly, then you want to prevent scrolling of the main content when the mouse is over a div (let's say a sidebar). For that, the sidebar may not be a child of the scrolling container of the main content (which was the browser window), to prevent the scroll event from bubbling up to its parent.
This possibly requires some markup changes in the following manner:
<div id="wrapper">
<div id="content">
</div>
</div>
<div id="sidebar">
</div>
See it's working in this sample fiddle and compare that with this sample fiddle which has a slightly different mouse leave behavior of the sidebar.
See also scroll only one particular div with browser's main scrollbar.
this disables the scrolling on the window if you enter the selector element.
works like charms.
elements = $(".selector");
elements.on('mouseenter', function() {
window.currentScrollTop = $(window).scrollTop();
window.currentScrollLeft = $(window).scrollTop();
$(window).on("scroll.prevent", function() {
$(window).scrollTop(window.currentScrollTop);
$(window).scrollLeft(window.currentScrollLeft);
});
});
elements.on('mouseleave', function() {
$(window).off("scroll.prevent");
});
You can inactivate the scrolling of the whole page by doing something like this but display the scrollbar!
<div onmouseover="document.body.style.overflow='hidden'; document.body.style.position='fixed';" onmouseout="document.body.style.overflow='auto'; document.body.style.position='relative';"></div>
$this.find('.scrollingDiv').on('mousewheel DOMMouseScroll', function (e) {
var delta = -e.originalEvent.wheelDelta || e.originalEvent.detail;
var scrollTop = this.scrollTop;
if((delta < 0 && scrollTop === 0) || (delta > 0 && this.scrollHeight - this.clientHeight - scrollTop === 0)) {
e.preventDefault();
}
});
Based on ceed's answer, here is a version that allows nesting scroll guarded elements. Only the element the mouse is over will scroll, and it scrolls quite smoothly. This version is also re-entrant. It can be used multiple times on the same element and will correctly remove and reinstall the handlers.
jQuery.fn.scrollGuard = function() {
this
.addClass('scroll-guarding')
.off('.scrollGuard').on('mouseenter.scrollGuard', function() {
var $g = $(this).parent().closest('.scroll-guarding');
$g = $g.length ? $g : $(window);
$g[0].myCst = $g.scrollTop();
$g[0].myCsl = $g.scrollLeft();
$g.off("scroll.prevent").on("scroll.prevent", function() {
$g.scrollTop($g[0].myCst);
$g.scrollLeft($g[0].myCsl);
});
})
.on('mouseleave.scrollGuard', function() {
var $g = $(this).parent().closest('.scroll-guarding');
$g = $g.length ? $g : $(window);
$g.off("scroll.prevent");
});
};
One easy way to use is to add a class, such as scroll-guard, to all the elements in the page that you allow scrolling on. Then use $('.scroll-guard').scrollGuard() to guard them.
If you apply an overflow: hidden style it should go away
edit: actually I read your question wrong, that will only hide the scroll bar but I don't think that's what you are looking for.
I couldn't get any of the answers to work in Chrome and Firefox, so I came up with this amalgamation:
$someElement.on('mousewheel DOMMouseScroll', scrollProtection);
function scrollProtection(event) {
var $this = $(this);
event = event.originalEvent;
var direction = (event.wheelDelta * -1) || (event.detail);
if (direction < 0) {
if ($this.scrollTop() <= 0) {
return false;
}
} else {
if ($this.scrollTop() + $this.innerHeight() >= $this[0].scrollHeight) {
return false;
}
}
}

Categories

Resources