jScrollPane zero height on dropdown menus - javascript

I have some content displayed as a list within a div. By default, the div is hidden, but becomes visible once it's parent has the class ".open":
<li class="dropdown">
<a>Options</a>
<div class="dropdown-menu">
<div class="menu-scroll">
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
</div>
</div>
</li>
What happens is when I click the anchor within the list item, the list item receives the ".open" class, which enables displaying the ".dropdown-menu" . Now my problem is that I want that menu to have a max-height of say 200px, after which it should initialize the scroll. Considering that each of it's list items are 50px tall, we would have these scennarios:
2 list items, height of 100px, no scroll
3 list items, height of 150px, no scroll
4 list items, height of 200px, no scroll
5+ list items, height of over 200px and SCROLL
This means I can't set a fixed height for .menu-scroll, since I want it to scale until reaching that height. What I do is set:
max-height: 200px;
height: auto;
It works perfect the first time I trigger the dropdowns but afterwards it renders everything wrong, like this:
What I've tried:
Initializing jScrollpane when clicking the anchor that toggles the .open class.
Initializing jScrollpane on document ready and only reinitializing the object when clicking the same anchor.
The results are the same everytime, as shown in the illustration above. I've searched the documentation, FAQ, StackOverflow, Google Groups but to no avail. Does anyone have any clues on this?
EDIT: This is the code I use to trigger the dropdown and initialize the scroll:
$('.dropdown-toggle').on("click", function() {
$(this).parent('.dropdown').toggleClass('open').find('.dropdown-menu').jScrollPane();
});
What the .open class does is add
.dropdown.open .dropdown-menu {
display: block;
}
to the otherwise hidden .dropdown-menu:
.dropdown.dropdown-menu {
display: none;
}

if you get it right on first trigger and then it fails after that implies you have to check your script. Can you post your script here?

Related

How can I make an element visible on a page only when the html content height is bigger than the viewport height?

I have this page which is basically a to do list, where you can add an infinite number of tasks of every kind, and of course, if you add a lot of tasks the height of the page is going to get bigger, and the scollbar is going to appear. I also have this button fixed at the bottom right of the page, and its only function is to send you back to the top of the page.
What I would like to do is to set the button's display to none only in case the page height is not bigger than the viewport height (so it can't scroll), because it would just be useless in this case, and then set its display to block in case the page has become higher than 100vh.
A simple way to do this is to check if the window.scrollY position value is 0. If not, you can assume that the page content is taller than the viewport and that the page is scrolled, so you can show/hide a "back to top" button accordingly. For example:
Javascript
window.addEventListener('scroll', () => {
const toTopLink = document.getElementById('toTopLink');
if (window.scrollY > 0) {
toTopLink.classList.remove('hidden');
} else {
toTopLink.classList.add('hidden');
}
});
HTML
<ul>
<li>List Item</li>
<li>List Item</li>
<li>...</li>
</ul>
<a id="toTopLink" class="hidden" href="#">Scroll to Top</a>
CSS
#toTopLink {
display: block;
position: fixed;
/* ... */
}
#toTopLink.hidden {
display: none;
}
Here's a fiddle showing this solution in action (note that you will need to resize your window height accordingly to see scroll behavior):
https://jsfiddle.net/dwq4h82x/8/
Smooth scroll and fade in/out of button
For some added goodness, you could do something like this instead of toggling display: none:
https://jsfiddle.net/6bjhvte4/3/
I'm haven't tested it but I'm pretty sure this could be done with #media queries:
.topbutton {
display: none;
}
#media screen and (min-height: 100vh) {
.topbutton {
display: block;
}
}

How to put menu after other instead of over each other

I have 3 menus in 3 different location on a website that they translate to one mobile toggle menu on phone.
My problem on mobile the 3 menus are showing up in the toggle panel but one over the other instead of one after the other. I define that this is a menu in my html using .main-nav
I tried appending .main-nav again but it doesn't work, I tried giving each menu a top margin in css it shows but along with its background.
live example - here how it is on codepen https://codepen.io/anon/pen/VOeKpE
I want all 3 menus in the website to show the links one after the other instead of over each other now.
if ($('.main-nav').length) {
var $mobile_nav = $('.main-nav').clone().prop({
class: 'mobile-nav d-lg-none'
});
$('body').append($mobile_nav);
$('body').prepend('<button type="button" class="mobile-nav-toggle d-lg-none"><i class="fa fa-bars"></i></button>');
$('body').append('<div class="mobile-nav-overly"></div>');
$(document).on('click', '.mobile-nav-toggle', function(e) {
$('body').toggleClass('mobile-nav-active');
$('.mobile-nav-toggle i').toggleClass('fa-times fa-bars');
$('.mobile-nav-overly').toggle();
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav class="main-nav float-right d-none d-lg-block">
<ul>
<li>home</li>
<li>about</li>
</ul>
</nav>
how it looks now
now
desired result
result needed
You could either use
li { display: inline-block }
Or
li { float: left;}
in your css.
the <li> element is by default styled with the display: block property. meaning it behaves similarly to an element like <p> or <div>, taking up the whole width of the content.
Changing this display property to inline-block ensures you still have the same functionalities you would also have with display: block but the elements will from now on only take up as much space as they need.

Show current section's heading in a fixed position on side

For a one-page layout website I would need the current section's heading to display in a fixed position on the left side of the screen in order to show the user where he currently is.
The heading will probably have an icon on its left side. I would like the floating heading to be only visible when the user is scrolling on the page, thus disappear when he halts, while the icon stays visible all the time. Is that possible?
This is possible, and most easily done in JQuery. In CSS using
position: fixed;
Will allow you to position a element, then it'll stick where it is on the screen, regardless of the user scrolling up and down the page. Using this JQuery code:
$(window).scroll(function(){
}
Will detect when the user scrolls then will run whatever is inside of the function. If you put this inside of the function:
$("#scrollerbar").css({"display": "block"});
clearTimeout($.data(this, 'scrollTimeout'));
$.data(this, 'scrollTimeout', setTimeout(function() {
$("#scrollerbar").css({"display": "none"});
}, 250));
With this HTML:
<div id="scrollerbar">You're scrolling</div>
And the following CSS:
#scrollerbar{
display: none;
position: fixed;
top: 50px;
left: 0;
}
This will create and position the div scrollerbar 50px down the page and set it to be invisible. Then whenever the user scrolls, it will set the scrollerbar to display: block (which makes it visible). Then stops the timeout "scrollTimeout" (if it's running). Then create the timeout "scrollTimeout" what will wait 250 milliseconds then set scrollerbar to invisible again.
Here's a JSFiddle: http://jsfiddle.net/Xanco/5q6oq8tm/
Please contact me if you have some questions.
EDIT
In order to answer the first part of your question, I've updated the JSFiddle: http://jsfiddle.net/Xanco/5q6oq8tm/2/
The scrollerbar contains a set of list items, each will be bound to a div:
<li id="1read">Reading 1</li>
<li id="2read">Reading 2</li>
<li id="3read">Reading 3</li>
<li id="4read">Reading 4</li>
There's also a new class name:
.active{
font-weight: bold;
}
I've created a function that will remove all "active" class names from the list items in the scrollerbar:
function removeActive(){
$("#1read").removeClass("active");
$("#2read").removeClass("active");
$("#3read").removeClass("active");
$("#4read").removeClass("active");
}
And now whenever the user scrolls, JavaScript will check what the user is currently reading and add the "active" class to the appropriate list items in the scrollerbar:
if ($("#1").is(":hover")) {
removeActive();
$("#1read").addClass("active");
}
if ($("#2").is(":hover")) {
removeActive();
$("#2read").addClass("active");
}
if ($("#3").is(":hover")) {
removeActive();
$("#3read").addClass("active");
}
if ($("#4").is(":hover")) {
removeActive();
$("#4read").addClass("active");
}
EDIT 2
Now, the JavaScript will take the innerText of a child of the hovered div with the ID "articleheader" instead of using a non-standard attribute, as demonstrated by this line of code:
$("#displayaArticleName").text($(this).children("#articleheader")[0].innerText);
Here is the JSfiddle: http://jsfiddle.net/5q6oq8tm/6/
Please note that there are no set of attributes that can only be used, you may use custom attributes, as demonstrated here: http://jsfiddle.net/5q6oq8tm/4/

Make Menu have a slideToggle Effect and push below elements down

I'm using a nice Mega Menu from CODROPS and I'm trying to customize it to have:
1) a slideToggle effect
2) When the menu is opened to push the below div element down (IE: not overlapping the below elements)
Here is my JS FIDDLE
This is what I've done so far:
1) I know very basic jquery and usually I know how to apply a slideToggle effect but I can't seem to get it right with their javascript code, so I'm left guessing where to place it but having no success. I've tried researching online but can't find a solution.
2) To make the element below the menu get pushed down, I know to make the position relative in the css below but that just breaks the menus float when it's activated.
/* sub-menu */
.cbp-hrmenu .cbp-hrsub {
display: none;
position: absolute;
background: #47a3da;
width: 100%;
left: 0;
}
It would be nice to have the elements below pushed down but the slideToggle effect is a bit more important to me...
You'll have to refactor this a bit to get it to work the way you want it to.
The .cbp-hrsub element containing the sub text is positioned absolutely, overlaying any text below. You would need to remove position:absolute to revert to the browser default position:static.
However, as the .cbp-hrsub element is part of each menu <li>, this pushes the other <li> elements down.
I'd suggest splitting the HTML out so that your menu <li> elements are separate to your sub text elements. Contain the subtext elements in a new <ul> and get these to slide down on click of the associated menu item link.

How to make a div of fixed height and width scroll horizontally when childs are not more visible?

I need to create a sort of cart, where I store elements created by the user.
I've created a simple scheme to help you understand my needs:
.buttons are two div containing an image (an arrow), where I'll bind an onclick event to scroll elements (#scroller). The layout has fixed sizes, thus the exact length of ul#scroller (the element that will contain items and that needs to be scrolled) is 900px.
I think the size of any #scroller child <li> will be ~100px.
There's a button (not present in the scheme) that allows the user to store in #scroller an item.
Actually when there are too many items the next will go on the bottom (beginning a new line). Instead I'd like that the new elements go ahead on the same line, but hidden (without hit #button_right).
I was thinking to do this with javascript, storing elements in an array, and keeping visible only the first 9 (x 100px), then by clicking on the arrow (let's say, the right one) hide the first item and show the 10th.
Do you think this is a good solution?
If not, what do you suggest? What CSS rules could help me to do it?
Thanks in advance.
you need to create an extra div with a very long width, and put it inside #scroller and make #scroller have an overflow: hidden so it doesn't show the scrollbar.
like this:
html:
<div id="scroller">
<div id="inner">
(your items)
</div>
</div>
css:
#scroller {
width: 900px;
overflow: hidden;
}
#inner {
width: 90000px;
}
P.S. now the items won't go to another line but you need to code the buttons so they scroll the content depending on the number of items, depending on their width behing the same it can be more simple or not.

Categories