overflow div area with many unordered list items - javascript

I have a div that contains a ul with a lot of li's. The div's height is smaller than the height the li's cover so I have overflow auto on the css for div.
sample html
<div class="points-area">
<ul class="points-list">
<li class="point selected" id="startPoint">Start</li>
<li class="point" id="endPoint">End</li>
<li class="point" id="N">Nasion</li>
<li class="point" id="S">Stella center</li>
<li class="point" id="P">Porion</li>
<li class="point" id="ar">Artikulare</li>
<li class="point" id="T1">T1</li>
<li class="point" id="Me">Me</li>
<li class="point" id="Gn">Gnathion</li>
<li class="point" id="T2/MT1">T2/MT1</li>
</ul>
</div>
css
.points-list{
list-style: none;
padding: 0;
margin-top: 0;
}
li.point{
border-bottom: 1px solid black;
padding: 0.1em;
}
.points-area{
overflow: auto;
height: 20em;
border: 1px solid black;
}
li.point.selected,
li.point:hover{
background-color: blue;
}
I have some javascript that when something user adds a circle on a kineticjs stage the next li gets selected (toggled selected class).
if (! $("li.point.selected").is(":last-child")){
prevLi = $("li.point.selected");
prevLi.next().toggleClass('selected');
prevLi.toggleClass('selected');
toBeAdded = prevLi.next();
}
so in my javascript code after a circle is added it toggles the 'selected' class name on the next li.
My problem is that because points are more than div's hieght can handle, the scrollbar doesnt move when I move down the li's. So e.g
scroll area reaches as far as li with text value porion. All li's bellow that are not shown cause of scrollbar. I need when changing from Porion Artikulare (toggling selected class) the overflow to scroll down a bit so that the li can appear on the div area. How can this be achieved?

It is very simple. all you need to know is 'you div height', 'li height', scrolltop and scrollto functions in JS / JQ.
calculate the scrollTop using number of li's u need to scroll, and use scrollTo inorder to scroll to particular position on scroll bar!!
if you have your codes in plnkr / JSFiddle etc.. please share it, i can help you with it

I think I got it! This is the updated fiddle
I added this piece of code
var divHeight, liHeight, lisPerScrollPage;
divHeight = $(".points-area").height(); //caluclate divs height
liHeight = $("li.point").outerHeight(true);// calculate li's height with padding margin etc
lisPerScrollPage = parseInt(divHeight / liHeight); //calculate how many li's fits a scroll page
Then I just checked to see if the li i am selecting is inside the scroll area and if its not move the scroll area as much ase needed. If the scroll area is allready lower and it can be shown don't do nothing (in case user manually used the scrollbar)
index = $("li.point").index(toBeAdded) + 1;
if ($(".points-area").scrollTop() < liHeight *(index - lisPerScrollPage))
{
$(".points-area").scrollTop(liHeight *(index - lisPerScrollPage));
}
I think it works as I want to.

Related

Make anchor link go some pixels above id

I'm currently working on a website and I'm having a trouble with anchors. My header is fixed and when I click on anchor it sends me on other page how it is supposed to be, but I'm missing 80 pixels which is height of my fixed header. There is a script that made accordion opened on new page when I click on anchor but it should scroll 80px less... here is some code I have over there in my .jsp file
<a href="${parentLink}#${menuItem.name}" class="${menuItem.classes[anchorClasses]}">
and there is a .js that makes my accordion opened on the new page
$(document).ready(function () {
if (location.hash != null && location.hash != "") {
$('.collapse').removeClass('in');
$(location.hash + '.collapse').collapse('show');
}
});
I think that you guys will need more info, so ask me anything that could help you. I'm new in this and I don't even know which code should I post here to help you guys realize what the problem is... Thank you (:
One common way is to add an invisible pseudo element to the original target element of the link via CSS, like this:
#your_anchor_id::before {
display: block;
content: " ";
margin-top: -80px;
height: 80px;
visibility: hidden;
pointer-events: none;
}
This will "extend" the element with that ID in a way which causes the anchor to be 80px above the main element, without causing any other visible changes.
Another idea is to use smooth scrolling with an offset. (View the example "Full Page" by clicking that link at top right of the snippet window)
$("nav ul li a").on('click', function(event) {
if (this.hash !== "") {
var myOffset = $('#myOff').val(); //get value from input (offset value)
if (myOffset==='') $('input').addClass('alert');
event.preventDefault(); // Prevent default anchor click behavior
var hash = this.hash; // Store hash
// jQuery animate() method for smooth page scroll
// 900 is the number of ms to scroll to the specified area
$('html, body').animate({
scrollTop: $(hash).offset().top - myOffset
}, 900);
} // End if
});
//$('div:contains(Section)').css('font-weight','bold');
html,body{margin:0;padding:0;font-family:Calibri;}
body{height:2500px;}
ul,li{margin:0;padding:0;}
*{box-sizing:border-box;}
section{
display: grid;
place-items: center;
width: 100%;
height: 500px;
}
nav{position:fixed;width:80vw;background:white;border:1px solid red;}
::placeholder{color:#ccc;}
nav ul li{
display: inline-block;
padding:0;
border: 1px solid rgba(200,200,200,0.3);
}
nav ul li:hover{background: #ddd;}
a{text-decoration:none;padding:10px 25px;display:inline-block;}
#one{background:palegreen; padding:50px;}
#two{background:palegoldenrod;}
#twa{background:lightblue;}
#fer{height:1500px;}
.alert{border:1px solid red;background:#ffc0cb99;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<ul>
<li>NAV / HEADER:</li>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li><input id="myOff" type="text" placeholder="Offset (e.g. 75):" /></li>
</ul>
</nav>
<section id="one">
<div>
<div style="text-align:center">Section One</div>
<div>Directions:<br>(a) View as Full Page (link at top right)<br>(b) Enter offset number (for how many pixels the smooth-scroll will stop short)<br>(c) Click nav "Two" or "Three" and observe<br>(4) Repeat using a different offset value<br>Note: The fixed header is deliberately not full width in order to show the top of the next section scrolling UNDER the header (undesireable) The offset prevents that, and is what you are asking about.</div>
</div>
</section>
<section id="two">
Section Two
</section>
<section id="twa">
Section Three
</section>
<section id="fer">
Section Four
</section>
Example code ripped off from:
w3schools Company Theme example

Reveal nav when scrolling down

What I'm trying to achieve is when a page is scrolled down the navigation is hidden - as in it disappears off the top of the screen like it traditionally would. When a user scrolls back up the page, the navigation slides into view again. Likewise, if you scroll down again, it's hidden.
I've tried a few different plugins for this and they nearly work. The one I'm currently looking at is "jquery-unveiled-navigation"
Link: https://github.com/weaintplastic/jquery-unveiled-navigation
Example: http://codepen.io/weaintplastic/full/RNpXOO/
This very nearly does what I want it to. It could do with some classes once the script is 'active'. As I only want to add a background-color when the script is 'active'. So it would be transparent until the navigation had left the screen and wasn't at the top.
Also, I know with this navigation if you scroll back up so half the navigation is in view, it will quickly adjust so you can see the bar in it's entirety. But I quite like the idea of it only showing as much as you've scrolled up by. So if the nav is 100px tall, and you scroll 30px, you only see the bottom 30px of the bar. Scrolling back down would hide the bar again, pixel by pixel - does that make sense?
So the steps would be (if this makes it clearer):
Header at the top of the page, transparent background.
When scrolling down, pixel by pixel the navigation leaves the screen.
When the user scrolls back up, the header starts to reveal it's self again - this time is has a background-color.
Once header hits the top of the browser again, the background is removed.
My markup is pretty simple. The bar only holds a logo and navigation toggle as the nav is hidden until the toggle is clicked, which displays the nav full screen.
<header class="page-head">
<span>Menu</span>
<nav class="site-nav">
<ul class="site-nav__list">
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
</ul>
</nav>
</header>
I've removed the SVG I have within page-head__home-link otherwise it would be a wall of code!
Hope someone can help :)
You can do this pretty easily without jquery or a library. You just need to watch the scroll event and when the direction changes place the header just above the field of vision and then as you continue to scroll make sure it never moves off of the top of the parent container.
var body, direction, margin, pageHead, pageHeadHeight, scrolled;
body = document.getElementById('tall');
scrolled = 0;
direction = null;
pageHead = document.getElementsByClassName('page-head')[0];
pageHeadHeight = pageHead.offsetHeight - 1;
margin = 0;
body.addEventListener("scroll", function(event) {
if (scrolled < body.scrollTop) {
direction = 'down';
} else {
if (direction === 'down') {
direction = 'up';
margin = Math.max(0, body.scrollTop - pageHeadHeight);
}
if (margin > body.scrollTop) {
margin = body.scrollTop;
}
pageHead.style['margin-top'] = margin + 'px';
}
return scrolled = body.scrollTop;
});
.tall {
background-color: blue;
min-height: 3000px;
min-width: 100%;
}
#tall {
max-height: 180px;
border: 3px solid pink;
overflow: auto;
}
.page-head{
color: white;
display: inline-block;
}
a {
color: white;
}
<div id="tall">
<div class='tall'>
<header class="page-head">
<span>Menu</span>
<nav class="site-nav">
<ul class="site-nav__list">
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
</ul>
</nav>
</header>
</div>
</div>

Css scroll bar auto scrolling with added content

I have div with fixed width and height. Div contains unordered list and has css overflow-y: scroll property. In javascript I have function which triggers when user click button below list, and that function adds one list item. When there is too much content inside div, new list items are added at the bottom of list and user needs to scroll list in order to see new list items. Is it possible somehow to make scroll bar auto scroll along with new content added, so that last added list item would be always visible?
Html:
<ul id="scroll">
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
<button type="button" id="click">Click</button>
Css:
ul {
height: 100px;
width: 100px;
overflow-y: scroll;
border: 1px solid black;
}
Javascript:
function addListItem(){
var message = document.createElement('li');
message.innerHTML = 'd';
document.getElementById('scroll').appendChild(message);
}
document.getElementById('click').addEventListener('click', addListItem, true);
JS fiddle link: https://jsfiddle.net/8gjhatvt/2/
Set the Element.scrollTop property of the scrolling div to be the position of the new element in the page + the new element's offset in its parent.
For example in the addListItem() function add the following line:
document.getElementById('scroll').scrollTop = message.offsetHeight + message.offsetTop;
Working fiddle: https://jsfiddle.net/rvnj6mc3/
Add this code to addListItem() function:
var scroll=document.getElementById("scroll");
scroll.scrollTop = scroll.scrollHeight;

Bootstrap Pagination between navigation elements

I tried different plugins like bootstrap-paginator and bootstrap-pagination-js to make pagination through dynamically generated <li> elements , so that they don't exceed one line.
The wanted result : One line of dates with next and previous buttons respectively in the right and in the left .
The plugins that I've tried have not been useful to me .
My code looks like this:
<div class="row">
<div class="col-md-12 column">
<ul class="nav nav-pills center-pills text-center">
<li class="active">
<a href="#">
<span class="text-center badge pull-right span-list">1</span>
1 Mars
</a>
</li>
<li class="">2 Mars</li>
<li class="">3 Mars</li>
<li class="">4 Mars</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
</ul>
</div>
</div>
The code fiddle .
Your suggestions will be very welcome .
Are you having a problem with styling? If so...
I've set the row height to fixed, and made overflow hidden, so that you get just one row of buttons.
.row{overflow:hidden;height:42px;}
I've added a prev and next button, and made them float left and right respectively. I hope this doesn't violate your pagination framework. Please let me know if you want an example of how to programmatically add these elements.
HTML
<li class="next">Next</li>
<li class="prev">Previous</li>
CSS
li.next{float:right;}
li.prev{float:left;}
I believe this gives the desired result... please let me know if I've missed your intention.
Disclaimer: I've only tested this in Opera 19.0. I don't have access to Firefox/Chrome/IE at the moment.
Example: http://jsfiddle.net/nickg1/5ELfQ/2/
Updated: Updated to remove horizontal scrollbar. - http://jsfiddle.net/nickg1/5ELfQ/3/
I have had success with Bootstrap pagination. If you are generating too many elements to fit in your desired space, you need to either figure out a way to generate less or use css to limit the size of your pagination space and "cut off" the overflowing elements.
What you can do is .prepend() a left li and .append() a right li:
$(document).ready(function () {
$('.nav').prepend('<li class="left"><a>Left</a></li>');
$('.nav').append('<li class="right"><a>Right</a></li>');
});
Although there has little browser compatibility and styling issues in this solution. But I hope this will give you an idea to start.
My CSS:
.nav.nav-pills {
width:auto;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
position: relative;
padding-right: 38px;
display: inline-block;
}
.nav-pills > li {
display: inline-block !important;
float: none !important;
}
.nav-pills > li.last {
position: absolute;
right: 0;
}
As display:inline; is applied to .nav, so for centering use text-center class in wrapping div. i.e.
<div class="col-md-12 column text-center">
Apply jQuery for previous/next buttons and resizing issues.
$(document).ready(function () {
$('.nav').prepend('<li>«</li>');
$('.nav').append('<li class="last">»</li>');
var ulWidth = $('.nav').width();
var screenWidth = document.body.clientWidth;
if (screenWidth < ulWidth ){
$('.nav').css('width', '100%');
}
$(window).resize(function(){
screenWidth = document.body.clientWidth;
screenWidth < ulWidth == true ?
$('.nav').css('width', '100%') :
$('.nav').css('width', 'auto');
});
});

Trouble redefining div height in slidedown menu

I'm having trouble with redefining the height property of a div that acts as a background for a dropdown menu. The idea is that when you click on an item in the list, the nested list and background div slide out, and then if you click on another item in the main list, the first nested list and background div slide up, the new list and the background div then slide down. My touble is that the background div height isn't getting redefined, and it keeps the height of the first list. Here's my jquery:
$(function() {
$( "ul.hmenu li a" ).click(function() {
var parentUlHeight = $("ul.hmenu").outerHeight(true) - 1;
var newUlHeight, oldUlHeight;
// REMOVE OLD SELECTION
$(".currentSelection").siblings('ul').slideUp("fast"); //find old selection and slide up its sibling ul
oldUlHeight = $(".currentSelection").siblings('ul').height();
$('#subnavdiv').slideUp("fast");
$(".currentSelection").removeClass("currentSelection"); //remove the class from the old selection
// MAKE NEW CURRENT SELECTION
$(this).addClass("currentSelection");
newUlHeight = $(".currentSelection").siblings('ul').height(); //calc height of new current selection subnav
$(this).siblings('ul').slideDown("slow");
// ANIMATE DIV BACKGROUND
$('#subnavdiv').css( "top", parentUlHeight + "px" ); //position div at right height
$('#subnavdiv').height( newUlHeight ); // set height to new selection height -- NOT WORKING
$('#subnavdiv').slideDown("slow");
});
});
HTML:
<nav class="nav clearfix desktop-nav" style="left: 146px;">
<ul class="hmenu">
<li class="item-103 current active">Home
<li class="item-105 deeper parent">
Our Team
<ul class="hmenu-left-to-right" style="">
<li class="item-145">link</li>
<li class="item-146">link</li>
</ul>
</li>
</ul>
<div id="subnavdiv"></div>
CSS
#subnavdiv {
width: 900px;
background: #607852;
display: none;
position: absolute;
-webkit-border-radius: 0 0 25px 25px;
-moz-border-radius: 0 0 25px 25px;
border-radius: 0 0 25px 25px;
}
Any Help is much appreciated!
This should get you close to what you're looking for
http://jsfiddle.net/F9De4/
you might instead add a class name ".main-link" to your anchor tag instead of "ul.hmenu li a"
$(".main-link").toggle(function(){
var newUlHeight = $(this).parent().find(".hmenu-left-to-right").height();
$(this).parent().find(".hmenu-left-to-right").hide("fast");
$('#subnavdiv').hide();
$("#subnavdiv").css("height",newUlHeight);
$('#subnavdiv').slideDown("slow");
},function(){
var newUlHeight = $(this).parent().find(".hmenu-left-to-right").height();
$(this).parent().find(".hmenu-left-to-right").show("fast");
$('#subnavdiv').hide();
$("#subnavdiv").css("height",newUlHeight);
$('#subnavdiv').slideDown("slow");
});

Categories