Twitter Bootstrap scrollspy always selecting last element - javascript

I have an issue with scrollspy, recreated in this fiddle:
http://jsfiddle.net/jNXvG/3/
As seen in the demo, the ScrollSpy plugin always keeps the last menu item selected no matter the scrolling position. I've read other questions and answers and tried different combinations of offset, etc., but none of them have helped. I can't figure out what's wrong.
I don't want to edit my template to include ugly html 'data' tags, so I am calling scrollspy() via JavaScript to activate the plugin.
The next step would be to remove the fixed content height and use 'affix' on the sidebar.

I had the exact same problem and for me, adding height: 100% to the body element was the fix.
(stricly nothing else seemed to make it work)

You need to attach the ScrollSpy to the element that is going to trigger scroll events, rather than the menu that is going to reflect the scroll position:
$('#content').scrollspy();​
JSFiddle

FYI: To get my desired effect (same one as on the Twitter Bootstrap docs page) I needed to set 'body' as my target element...I could not get scrollspy'ing to work by using the immediate parent of the elements I wanted to spy as the target.
(It just auto-selected the my last element always)

In my case, Firefox was always selecting the last element and it was NOT the
height:100%;
on the body that was causing the problem (as I didn't have anything like that).
It was a
position:absolute;
on a container div.
Hope it helps someone out there...

I fixed it using body height 100% but it didnt work on Firefox. After wasting so much time found the answer on github page. Applying height 100% to HTML tag fixes the issue both for Chrome and Firefox.
https://github.com/twbs/bootstrap/issues/5007

When calling the scrollspy method you typically specify the body tag and the nav element.
<script>
$(function() {
$('body').scrollspy({ target: '#faq_sidebar' });
});
</script>
The JavaScript above is equivalent to:
<body data-spy="scroll" data-target="#faq_sidebar">
The only situation where you do not specify the body tag is if you want to track an element with a nested scrollbar like in the JSFiddle above.

If anyone else's issue wasn't solved by the suggestions above try adding <!DOCTYPE html> to the first line of your page. This was a simple step which solved the problem for me.

I had this same problem; removing the height: 100% from the <body> element fixed this for me.

I had a similar issue where scroll spy would not work on anything but a body tag so I actually went into the bootstrap js found the Scroll spy (SCROLLSPY CLASS DEFINITION) section and changed this line:
, $element = $(element).is('body') ? $(window) : $(element)
to this:
, $element = $(element).is('body') ? $(window) : $(window) //$(element)
(note that the element after the // is a comment so I don't forget I changed it)
And that fixed it for me.

ScrollSpy is pretty unforgiving and the documentation is sparse to say the least...there are different and conflicting fixes for this based on your implementation...
Nested content was my problem. This fixed it for me:
(1) make sure all hrefs in your nav match a corresponding ID in your spied upon target container.
(2) If the items in your spied upon content container are nested then it won't work...
This:
<ul class="nav" id="sidebar">
<li>
<a href="#navItem1" />
</li>
<li>
<a href="#navItem2" />
</li>
</ul>
<div id="spiedContent"> <!-- nested content -->
<div id="navItem1">
<div id="navItem2"></div>
</div>
</div>
To This:
<ul class="nav" id="sidebar">
<li>
<a href="#navItem1" />
</li>
<li>
<a href="#navItem2" />
</li>
</ul>
<div id="spiedContent"> <!-- flat content -->
<div id="navItem1"></div>
<div id="navItem2"></div>
</div>
All good!
My guess if you looked at the scrollspy code its not looking past the first child of the spied container for the ids.

Make sure you're not mixing implementations. You don't need $('#content).scrollspy() if you have data-spy="scroll" data-target=".bs-docs-sidebar" on your body tag.

I think that this might be a bug in ScrollSpy.
I also had the same problem and when I stepped through the code I could see that the offset for all the targets were the same (-95px). I checked where these were being set and it was using the position() function. This returns the position of the element relative to the offset of the parent.
I changed this to use the offset() function instead. This function returns the position of the element relative to the offset of the page. Once I did this then it worked perfectly. Not sure why this isn't the default behaviour.
The reason that the position() function wasn't working in my case was because I had to have an empty div which was actually absolutely positioned 95px above the top of its container. I needed this as my target so that the headings weren't hidden behind my header that was fixed to the top of the page.

When I was trying to figure out this issue, I used some of what Mehdi Benadda said and added position: relative; to the body. I added this to the stylesheet:
body {
position: relative;
height: 100%;
}
Hopefully this helps someone in the future.

You don't have to call method scrollspy().
Also you don't need set height: 100% anywhere.
All you need is:
position: relative; for body
add data-bs-spy="scroll" to your content or body
add data-bs-target with navbar id
https://i.imgur.com/M5jib0t.png
It helps me.

It seems that scroll spy work only when used container has a scrollbar (Tested with bootstrap 5).
You can put data-bs-spy="scroll" and data-bs-target="#target-nav" attributes in the nearest parent having a scrollbar.

In my case, i had added the scrollspy component of bootstrap version 5.2.3 but my bootstrap js cdn was 5.0. After i added the 5.2.3 js cdn, it worked!
You may also add the downladed bootstrap js files as well.
And make sure to add the bootstrap css cdn too!

Related

Bootstrap tooltip initialises but isn't showing up

Before marking this question as a duplicate, I know there is one exact same question with the exact same problem but the solution isn't working for me. Here is the link to that question.
The problem is, I know tooltips are being initialized because when I hover over my button, this markup shows up in my DOM.
<div class="tooltip fade top in" style="top: -34px; left: 20.5px; display: block; "><div class="tooltip-arrow"></div><div class="tooltip-inner">Add Quotation.</div></div
But it isn't showing up in the browser! In case of inspect element, It shows me the exact tooltip but it isn't appearing. It's transparent! The JSfiddles and all are working but it's not working in just my code.
I am using Laravel Mix with Vue.js. Anything extra is to be done or I am missing something?
UPDATE: I have already added data-toggle, data-placement and title in my element on which I want a tooltip.
Although we need additional information ...
what you are describing is usually related to the parent position.
Try attaching the tooltip to the body when initializing it like so.
// AN EXAMPLE ELEMENT
<div class="tip" title="Some tooltip"></div>
// THE JQUERY
$('.tip').tooltip({
container: 'body'
});
Let me know if this changes things and please add your initialization code
and the item your attaching the tooltip to css position
Live Example:
https://jsfiddle.net/sagive/aq9Laaew/137936/

Cycle2: pager only displays link to first slide and hides the others

I'm using Cycle2 with its carousel plugin. I tried to add their pager functionality to my page, like this:
First, I created the container div:
<div id="concluidos-navigation" class="cycle-pager"></div>
Then, I set the plugin options like this:
<ul class="cycle-slideshow"
data-cycle-slides="> li"
data-cycle-fx=carousel
data-cycle-allow-wrap=false
data-cycle-pager="#concluidos-navigation"
>
The resulting HTML is this, for the first slide:
<span class="cycle-pager-active">•</span>
But for every other slide, the result is:
<span style="display: none;">•</span>~
Where does this "display: none" comes from? Am I missing something? If I inspect the element on Chrome and remove the "display: none", all links show up and work perfectly to navigate between slides.
Here's the fiddle
Ok, I was able to fix it with a workaround by overriding the default style. First I added this to the plugin initialization:
data-cycle-pager-template="<strong class='cycle-pager-nav-circle'><a href=#></a></strong>"
And then I added a CSS rule to the "cycle-pager-nav-circle" class:
display: inline-block !important;
However, if anyone as a more clean solution, please give your suggestions.
hide-non-active could be the reason perhaps. It defaults to true. [Link].

Bootstrap Responsive Collapsed Submenu has fixed height on first collapse

This problem can be exhibited in all (that I know of) Twitter Bootstrap versions. So, I have a navbar and when the screen is smaller, it becomes a collapsable tray. This behaviour can be seen on the bootstrap demo site. I also have submenus, which appear collapsed on the initial navbar expansion. The problem is, on the first collapse, the collapsable gets an explicit height set. If you close and expand again, the collapsable gets a height:auto;
So, when I click a submenu item, the dropdown is expanded, but it overflows due to the height being explicitly set.
My attempted solution was adding:
$(function() {
$('.nav-collapse').on({
shown: function() {
$(this).css('height', 'auto');
},
hidden: function() {
$(this).css('height', '0px');
}
});
});
This doesn't seem to affect it at all, I've deleted that code and it still has the same effect. If a JS Fiddle would help, I'd be happy to provide one, but you can see all of this on the Bootstrap demo site.
Thanks in advance,
Charles.
It bothered me a little, and after some searching, I found that the problem can be solved by adding the .collapse class to the .nav-collapse element.
Working demo (jsfiddle)
One of those time when we just say Meh.. I should have followed the doc to the letter (see Responsive navbar):
<div class="nav-collapse collapse">
<!-- .nav, .navbar-search, .navbar-form, etc -->
</div>
For posterity :
Found out thanks to this issue : https://github.com/twitter/bootstrap/issues/3788
I'm not sure if it really is related, but my debugging showed the problem on the first transition height resetting anyway (source) :
$.support.transition && this.$element[dimension](this.$element[0][scroll])
Bootstrap is setting the element style height to 280px on initialization of the collapse element.
I added this JQuery line in my ready() function right after my call to .collapse()
$("#avail_detail").collapse();
$("#avail_detail").css("height","auto");
And, now things behave as I expect.

CSS class depending on page position

I have a fixed navigation at the top of the page that has links that smoothly scroll you around to different sections (IDs) of the page via jQuery.
Would there be any possible way to have a css class (e.g. .current) appended to the navigation links depending on what section of the page you're at?
For example, when I click "About", it'll scroll down to the About section and also make the navigation text orange as long as you stay in that section?
I've seen this done somewhere a while ago but I don't remember the website or even how to describe this behavior to search for it.
EDIT: Here's a link to something siliar to what I'm looking for:
http://www.fat-man-collective.com/hello.php
The icons change depending on your position on the page.
Script:
<script>
function goToByScroll(id){
$('html,body').animate({scrollTop: $("#"+id).offset().top - 50},'500');
}
</script>
HTML:
About
[...]
<div id="about">
[...]
</div>
Any help is greatly appreciated.
This would be possible by examing the offset()* function of the desired element and then coding to respond accordingly. You can track the offset of an element, and depending on the resulting offset, you would apply or remove the appropriate classes accordingly.
*See the documentation for offset()
When you click on a section in the navigation, just modify the class so that the style is what you want it to be.
Secondly, you'll need to add an event handler on the scroll event that similar modifies the nav's class.
Try this:
function goToByScroll(id){
$('ul#nav li a').removeClass('active'); // elements in menu
$(this).addClass('active');
$('html,body').animate({scrollTop: $("#"+id).offset().top - 50},'500');
}
Four years later...for those that have the same question since hopefully the OP has solved his problem by now.
Check out Bootstrap's ScrollSpy plugin, which "is for automatically updating nav targets based on scroll position." For an example of using the ScrollSpy plugin see this detailed tutorial on how to make a floating, updating navbar (like the Bootstrap site uses).

jQuery Slide Toggle Not Working - Resolved

On the first click, it works as expected:
the class is changed
and the html content is changed from 'Show...' to 'Close...'
the content area is expanded with the slideDown effect,
Good so far.
On the second click, ...
the class changes
the html content is changed from 'Close...' to 'Show...'
The content area does NOT go away as expected.
On the third click, ...
the class is changed
the html content is changed
the already-shown content is re-shown with the slidedown effect.
So everything is working except for the 2nd click when the content is supposed to be hidden again.
Here's the jQuery:
-
$('.open_user_urls').live('click', function() {
$('#user_urls').slideDown('slow');
$(this).addClass('close_user_urls');
$(this).removeClass('open_user_urls');
$(this).html('Close Search History');
return false;
});
$('.close_user_urls').live('click', function() {
$('#user_urls').slideUp('slow');
$(this).addClass('open_user_urls');
$(this).removeClass('close_user_urls');
$(this).html('Show Search History');
return false;
});
Here's the HTML it's acting on:
<h3 class='open_user_urls'>Show Search History</h3>
<div id='user_urls'>
// an OL tag with content
</div>
And the only applicable CSS:
#user_urls { display: none; }
EDIT - I replaced my jquery code with functionally equivalent code supplied in an answer below, but the problem persists. So the cause must be elsewhere. I do recall this code working originally, but then it stopped. I'm stumped. Time to strip everything else out piece by piece...
EDIT 2 - Since the bug must be elsewhere, I'm accepting a code improvement for my jquery as the answer. Thanks.
Edit 3 - Found the source of the problem.
Inside the #user_urls div I have an series of OLs with the following css:
.url_list {float: left; width: 285px; list-style-position: outside; margin-left: 25px;}
Each OL contains a list of 20 urls and is meant to display in as many multiple columns as required to display all the URLs.
Removing the float: left; on these OL tags causes the problem to go away.
So having a float on the content contained in the DIV thats showing and hiding is causing it not not hide at all. Why would this happen?
EDIT 4: Adding a inside the #user_urls DIV allows the hiding action to work properly.
Perhaps something like this would be simpler?
$(".open_user_urls").toggle(
function () {
$(this).text("Close Search History").siblings(".user_urls").slideDown("slow");
},
function () {
$(this).text("Show Search History").siblings(".user_urls").slideUp("slow");
}
);
The toggle function is designed for precisely the scenario you're encountering.
To reiterate the problem and resolution to this question...
Inside the #user_urls DIV were a series of OL tags, each floated left. It was the float that was causing the problem.
Adding a <br style='clear: left;' /> inside the #user_urls DIV fixed the problem.
From what I've found, jQuery needs to have the height style set in order to slide it correctly. A work around I've used is to set the height before you slide it closed.
$('#user_urls').css('height', $('#user_urls').height() + 'px');
After you set it once, it should work correctly from then on. Check out this tutorial for a more detailed explanation.
Since this question was opened, jQuery have put in a fix for this themselves.
Updating to the latest version of jQuery solved the problem for us with no CSS changes. (jQuery 1.4.4 as of Dec 9th 2010)
Found via discussion on Google Groups in turn found from d12's answer. According to duscussion, in some jQuery 1.3x versions this bug affected several actions, slideUp, fadeOut, and toggle, if the element being hidden/slid up is a a non-floated parent containing floated children.
I think Conor's answer might put you on the right track. I might also suggest slideToggle and toggleClass:
http://docs.jquery.com/Attributes/toggleClass
http://docs.jquery.com/Effects/slideToggle
I could be as easy as:
$("h3.open_user_urls").click(function () {
next("div#user_urls").slideToggle();
});
I can't duplicate your bug. I used your exact code and I cannot replicate your issue.
This must be a script error from a different place in your JS code.
Thanks for this question. It really got me on my way figuring out the problem toggling an element with floated children.
Another resource that really helped and explains the behavior a bit can be found
on this Google group discussion.
Putting a non breaking space in your div is another solution similar to what The Reddest suggested that worked for me on a similar issue.

Categories

Resources