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;
Related
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
Currently, I have three tabs in my nav bar, BOARD, SKILLS, and ABOUT, all in one container with a boarder-bottom for the container. When I click on one of the divs, the appropriate div name is selected, to indicate which tab I am on. That is what is currently working and can be seen in my codePen.io:
What I have so far - click here
.
What I am trying to do is when I go from BOARD to SKILLS or BOARD to ABOUT, is to have a bar slide from one one tab to the next, rather than being static-like (which is what I have currently) e.g. a smooth scroller on click from one tab to the next. How can I go about doing this? I have no idea where to begin.
You can use this function to slide an element:
function scaleSlider(to) {
var $slider = $('.slider', '.tabs'),
$elSpan = to.find('span'),
width = $elSpan.width(),
left = $elSpan.position().left;
$slider.animate({
width: width,
left: left
});
}
In your HTML you need to add the .slider element:
<div class="col-md-8 tabs">
<div class="slider"></div>
<!-- your html here -->
</div>
CSS:
.tabs .slider {
position: absolute;
height:100%;
border-bottom: 4px solid grey;
}
So when you click a menu element you call scaleSlider:
$('.skills').on("click", function() {
//Your code here
scaleSlider($(this));
});
Please check out this demo: http://codepen.io/anon/pen/EyoBmg
I am building a website that expands horizontally as user takes action like http://portal.azure.com style. When they click a button(from a list) in one div, the details of the selected items appear in another div beside it. this can get really long and over flow the mother div.
I am looking for a way i can automatically scroll the page to the right most edge when a new div overflows.
layout
<div style="overflow-x: auto">
<div layout="row">
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
</div>
</div>
As you can see above, the first div shows by default but the other divs appear based on user interaction.
By the time the 3 div appears, it overflows.
How can i scroll to the right edge anytime it over flows? (you should really check out http://portal.azure.com to see what im talking about)
PS: i am using AngularJS. I am not using jquery. But i dont mind including it if its the only option
You can use plain Javascript for keeping the scroll to right.
Something like this:
var myDiv = document.getElementById("row");
myDiv.scrollLeft = myDiv.scrollWidth;
You need to fire the above function every time you add a new div. That way it will always automatically be scrolled when divs are dynamically added.
You will need to hook up the DOMNodeInserted event on your container. The function will be called whenever a div is added to your row container. This way you will not have to change anything in your existing code.
Here is a very simple example with dynamically added divs:
var num = 1,
btn = document.getElementById('btn'),
row = document.getElementById("row");
scroller(); // fire teh scroller right away for initial scroll
// function to keep it scrolled towards right
// function scroller() { row.scrollLeft = row.scrollWidth; }
// edited to add simple animation
function scroller() {
var maxScroll = row.scrollWidth - row.clientWidth; // required to stop
row.scrollLeft += 2;
if (row.scrollLeft < maxScroll) {
timer = window.setTimeout(scroller, 1000 / 60);
}
}
// hook up event to call scroller whenever an element is dynamically added
row.addEventListener("DOMNodeInserted", scroller);
// for demo to simluate dynamically adding divs
btn.addEventListener("click", function() {
var newDiv = document.createElement("div");
newDiv.setAttribute("class", "col");
num += 1; newDiv.innerText = num;
row.appendChild(newDiv);
});
div[layout] {
width: 500px; height: 140px; white-space: nowrap;
overflow: hidden; overflow-x: auto;
}
div.col { height: 140px; width: 400px; display: inline-block; text-align:center; }
div { border: 1px solid red; }
<div id="row" layout="row"><div class="col">1</div></div>
<button id="btn">Add</button>
Edit: Added simple animation using setTimeout (in order to keep jQuery away). Ideally you should be using requestAnimationFrame or a suitable library if you are already using one.
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.
I have a script that has a div with a width larger than its' parent, with the parent being set to overflow: hidden;. I have javascript that is setting the left positioning of the big div to create "pages". You can click a link to move between pages.
All of that works great, but the problem is if you tab from one "page" element to another, it completely messes up all the left positioning to move between the pages.
You can recreate this bug in the fiddle I set up by setting your focus to one of the input boxes on page ONE and tabbing until it takes you to page two.
I've set up a demo here.
The code that is important is as follows:
HTML:
<div class="form">
<div class="pagesContainer">
<div class="page" class="active">
<h2>Page One</h2>
[... Page 1 Content here...]
</div>
<div class="page">
<h2>Page Two</h2>
[... Page Content here...]
</div>
</div>
CSS:
.form {
width: 400px;
position: relative;
overflow: hidden;
border: 1px solid #000;
float: left;
}
.pagesContainer {
position: relative; /*Width set to 10,000 px in js
}
.form .page {
width: 400px;
float: left;
}
JS:
slidePage: function(page, direction, currentPage) {
if (direction == 'next') {
var animationDirection = '-=';
if (page.index() >= this.numPages) {
return false;
}
}
else if (direction == 'previous') {
var animationDirection = '+=';
if (page.index() < 0) {
return false;
}
}
//Get page height
var height = page.height();
this.heightElement.animate({
height: height
}, 600);
//Clear active page
this.page.removeClass('active');
this.page.eq(page.index()).addClass('active');
//Locate the exact page to skip to
var slideWidth = page.outerWidth(true) * this.difference(this.currentPage.index(), page.index());
this.container.animate({
left: animationDirection + slideWidth
}, 600);
this.currentPage = page;
}
The primary problem is that whatever happens when you tab from say, an input box on page one to something on page 2, it takes you there, but css still considers you to be at left: 0px;. I've been looking all over for a solution but so far all google has revealed to me is how to stop scrollbar scrolling.
Any help or suggestions would be appreciated, thanks!
P.S. The html was set up like this so that if javascript is disabled it will still show up all on one page and still function properly.
I updated your fiddle with a fix for the first tab with the form: http://jsfiddle.net/E7u9X/1/
. Basically, what you can do is to focus on the first "tabbable" element in a tab after the last one gets blurred, like so:
$('.form input').last().blur(function(){
$('.form input').first().focus();
});
(This is just an example, the first active element could be any other element)
Elements with overflow: hidden still have scrolling, just no scroll bars. This can be useful at times and annoying at others. This is why your position left is at zero, but your view of the element has changed. Set scrollLeft to zero when you change "pages", should do the trick.