Javascript stopping scroll from jumping - javascript

I have a page where you can click to slideDown an element from the top of the page.
I am trying to create a rule that says if the push down is visible and the screen has scrolled further than the height of the push down then it should be hidden again. Meaning the user will have to push the button to get it to show again.
In my HTML I have:
<div class="row" id="learn-more" style="display:none">
<div class="small-12 columns" id="close">
<p id="close-learn">
<i class="fa fa-times pull-right fa-2x"></i>
</p>
</div>
<div class="small-12 columns" id="learn-content">
<h1>Content for Pushdown</h1>
</div>
</div>
<div class="row" id="hero">
<div class="small-12 columns small-centered">
<p id="learn"><a class="transition">Learn More</a></p>
</div>
</div>
In my Javascript I have:
// Open and close learn more section
$("#learn").on("click", function() {
$("#learn-more").slideDown();
});
$("#close-learn").on("click", function() {
$("#learn-more").slideUp();
});
// Close learn-more based on scroll position
$(window).on("scroll", function() {
var scrollPosition = $(window).scrollTop();
if ($("#learn-more").is(":visible") && scrollPosition > $("#learn-more").height()) {
$("#learn-more").slideUp()
}
});
This all works but when the #learn-more element slides up the page jumps down about 500 pixels which is the height of the #learn-more element. I would like mine to work in the same way as Airbnb's new homepage when you click the 'how it works' button and then scroll below the push down element.
Any advice would be much appreciated.

Seems that this situation occurs because $(window).scrollTop position is preserved after the the slideUp() is called.
But we can memorize the visible position of Learn More button relative to the top of the window and after text block is hidden return to this position. Also, i suggest to use hide() instead of slideUp() here.
Here is what I suggest to do on scroll:
$(window).on("scroll", function(event) {
var scrollPosition = $(window).scrollTop();
var learnMore = $("#learn-more");
if (learnMore.is(":visible") && scrollPosition > learnMore.height()) {
var learnMoreButtonTop = $("#learn").offset().top - scrollPosition;
learnMore.hide();
$(window).scrollTop(learnMoreButtonTop);
}
});
Working example

Related

How to make sidebar fixed (without using actual "fixed" property) with javascript?

I’m a beginner and I’m stuck. And I would really use some help. Have two questions regarding js.
Namely, I have a sidebar on the left that has a toggle option. In order to solve the problem of keeping my sidebar in sight when scrolling, I added javascript code that constantly raises it to the top of the page. But that doesn't seem like the optimal solution.
Is there a way to use javascript to set the menu to be fixed to the top of the page whenever the toggle is open.
Here is the following js code:
$(function() {
var $sidebar = $("#menu"),
$window = $(window),
offset = $sidebar.offset(),
topPadding = 60;
$window.scroll(function() {
if ($window.scrollTop() > offset.top) {
$sidebar.stop().animate({
marginTop: $window.scrollTop() - offset.top + topPadding
});
} else {
$sidebar.stop().animate({
marginTop: 0
});
}
});
});
Here is the html:
<!-- Sidebar -->
<div class="bg-light border-right" id="sidebar-wrapper" style="background-image: url('geogebra6.png'); scroll-margin: 120px;"> <!--Dodao side baru scroll marginu -->
<div class="sidebar-heading">Sadržaj</div>
<div class="list-group list-group-flush" style="background-image: url('geogebra1.png');" id="menu">
<b>1. Uvod</b>
<b>2. Realni nizovi </b>
<!-- class="dropdown-toggle" style="color: black; "-->
<b>3. Funkcionalni nizovi</b>
<ul class="collapse list-unstyled" id="homeSubmenu" >
<li>
<b>3.1. Obična konvergencija</b>
</li>
<li>
<b>3.2. Ravnomerna konvergencija</b>
</li>
</ul>
</div>
</div>
Of course, using position:fixed does not get the job done because it breaks the flow and mu side bar has the toggle option.
While we are here, is there any way of editing this line of code to make sidebar closed by default and then to open when clicked on the button? I've tried several different solutions but none of them seems optimal.
Here is the code in question:
<!-- Menu Toggle Script -->
// $("#wrapper").toggleClass("toggled");
$("#menu-toggle").click(function(e) {
e.preventDefault();
$("#wrapper").toggleClass("toggled");
});
Here is the actual link of the site:
http://alas.matf.bg.ac.rs/~ml05184/

Angular 4 scroll a div a certain amount

I have a div whose height is given and it has overflow-y: auto, so when necessary it has a scrollbar.
Now I want to be able to scroll that div a certain amount on an event. So far I've been able to scrollIntoView(false) which just scrolls it to the bottom. I want to scroll it almost, but not quite to the bottom. I do not want to scroll the window, as this div is position: fixed relative to the window.
From what I've seen this is technically possible, but people keep referring to various plugins. Right now a plugin is not an option (maybe for some future release, but not now).
<form novalidate #searchFilterForm [formGroup]="filterForm" role="application">
<section id="searchFilters" role="form">
<div class="search-filter-tab" #searchFilterTab>
..
</div>
<div #searchFormContainer class="search-filter-container" >
<div class="search-filter-header">
...
</div>
<fieldset class="search-filter-checkboxes search-mobile-small" >
...
</fieldset>
<fieldset class="search-filter-sliders search-mobile-small" >
...
</div>
</fieldset>
<fieldset class="search-filter-dropdowns search-mobile-small" >
...
</fieldset>
<fieldset >
<span #scrollToHere></span>
<div class="search-filter-text-input-container search-mobile-small" *ngFor="let textItem of searchBoxList; trackBy: trackByFunc; let i = index;">
<app-auto-complete
#autoCompleteBoxes
...
(showToggled)="scrollToEndOfFilter($event)"
>
<input
type="text"
autocomplete="off"
[attr.name]="textItem.apiName"
[placeholder]="textItem.label"
[attr.aria-label]="textItem.label"
class="search-filter-text-input"
>
</app-auto-complete>
</div>
</fieldset>
</div>
</section>
</form>
Typescript:
scrollToEndOfFilter(ev){ //ev == {shown: true/false, ref: ElementRef}
if (ev == null || (ev.shown == true && ev.ref)){
this.searchFormContainer.nativeElement.scrollTop = 950;
}
}
How about standard approach:
Fist you assign a reference to your div like this:
<div #divToScroll></div>
then, you get a reference to your div:
#ViewChild('divToScroll') divToScroll: ElementRef;
and finally when you need to scroll you just call:
divToScroll.nativeElement.scrollTop = 30;
It becomes tedious when we need to scroll elements( let say a particular div inside *ngFor)
best way is to get the current position and height of element using :
dynamically assign id to each div [attr.id]=" 'section' + data.id"
<div id="parentDiv" #parentDiv>
<div *ngFor="let data of content" [attr.id]=" 'section' + data.id">
<p>section {{data.id}}</p>
<botton (click)="scrollMyDiv(data)"></button>
</div>
</div>
and in .ts
scrollMyDiv(item) {
let section = 'section' + item.id);
window.scroll(0, 0); // reset window to top
const elem = document.querySelector('#' + section);
let offsetTop = elem.getBoundingClientRect().top` - x;
window.scroll(0, offsetTop);
}`
getBoundingClientRect().top will give height from top. x is any constant value like the height of your header section.
its mostly used to provide scrollspy like feature.

Inline editing with icon on side

i'm trying to create an inline editing plugin for a new project, I'm working on. It should be very easy. Just an fa-pencil icon on side of the text, which should be edited.
Currently I've got HTML like so (simplified):
<div class="inline-edit-icon">
<i class="fa fa-pencil"></i>
</div>
<div class="inline-edit">
<p id="doctor-info-text" class="inline-edit-text">{{userInfo.description}}</p>
<textarea class="form-control inline-edit-input" ng-model="userInfo.description"></textarea>
</div>
And I'm triggering the visibility of the .inline-edit-icon div via jQuery:
$('.inline-edit-text').hover(function(e){
var coordinates = $(this).offset();
$('.inline-edit-icon').css('top', coordinates.top);
$('.inline-edit-icon').css('left', coordinates.left - $('.inline-edit-icon').width());
$('.inline-edit-icon').show();
}, function(){
$('.inline-edit-icon').hide();
});
The problem is, I can't click on the icon, as it gets hidden before I get my mouse to it.
How can I keep it visible when the mouse is over either text or icon?
Does this example help you? Notice the changes I made with HTML AND CSS:
$('.inline-edit-text, .fa-pencil').hover(function(e){
var coordinates = $(this).offset();
console.log(coordinates)
//$('.inline-edit-icon').css('top', coordinates.top);
//$('.inline-edit-icon').css('left', coordinates.left);
$('.inline-edit-icon').show();
}, function(){
$('.inline-edit-icon').hide();
});
JSFiddle
Add a container around your .inline blocks, and you trigger the hover on it.
Something like :
<div class="inline-container">
<div class="inline-edit-icon">
<i class="fa fa-pencil">o</i>
</div>
<div class="inline-edit">
<p id="doctor-info-text" class="inline-edit-text">{{userInfo.description}}</p>
<textarea class="form-control inline-edit-input" ng-model="userInfo.description"></textarea>
</div>
</div>
and the script part:
$('.inline-container').hover(function(e){
var coordinates = $(this).children('.inline-edit').offset();
var $icon = $(this).children('.inline-edit-icon');
$icon.css('top', coordinates.top);
$icon.css('left', coordinates.left - $icon.width());
$icon.show();
}, function(){
$('.inline-edit-icon').hide();
});
Working Fiddle: http://jsfiddle.net/qej24s5m/
Hope it's gonna help you.
You may want to use mouseenter and mouseleave events:
$('.inline-edit-text, .fa.fa-pencil').on('mouseenter',function(e){
var coordinates = $(this).offset();
$('.inline-edit-icon').css('top', coordinates.top);
$('.inline-edit-icon').css('left', coordinates.left - $('.inline-edit-icon').width());
$('.inline-edit-icon').show();
});
$('.inline-edit-text, .fa.fa-pencil').on('mouseleave',function(e){
$('.inline-edit-icon').hide();
});

Open Collapse Tab in Hover in Bootstrap

I am having Collapse Panel in Bootstrap which is opening on a click on the title of the tab. I am trying to figure out to open using the hover of the mouse on the total width of the tab but I am not getting it. Below is the code of the single tab which is close by default.
<div class="panel panel-default" style="background-color:#039;">
<div class="panel-heading" style="background-color:#039;">
<a class="nodecoration panel-title lead" data-toggle="collapse" data-parent="#panel-814345" href="#panel-element-566205">Software Development</a>
</div>
<div id="panel-element-566205" class="panel-collapse collapse" style="background-color:#039; color:#fff;">
<div class="panel-body" style="border:none; font-size:14px; padding-bottom:0; margin-bottom:0;">
We work for almost all web based application, database-driven systems, mapping and geo-spatial applications, and large content managed websites
<br /><br /><p style="font-style:italic; font-weight:700;">Find out more</p>
</div>
</div>
</div>
If we change the css class from class="panel-collapse collapse" to class="panel-collapse collapse in" then the tab is open. Could you please let me know how to achieve this.
I GOT THE ANSWER BUT WORKING ONLY BY HOVER ON THE TITLE NOT ON THE TOTAL WIDTH OF THE TAB. THE CODES ARE BELOW
$(function() {
$(document).on('mouseenter.collapse', '[data-toggle=collapse]', function(e) {
var $this = $(this),
href, target = $this.attr('data-target') || e.preventDefault() || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')
,
option = $(target).hasClass('in') ? 'hide' : "show";
$('.panel-collapse').not(target).collapse("hide");
$(target).collapse(option);
})
});
Can we make this to work by hover on the full width ??
You can achieve this with hover function
$(".panel-heading").hover(
function() {
$('.panel-collapse').collapse('show');
}, function() {
$('.panel-collapse').collapse('hide');
}
);
But it will close the panel as soon as mouse leaves the title header
Fiddle with hover
Alternate solution is mouseenter function
$(".panel-heading").mouseenter(function () {
$(".panel-collapse").fadeIn();
});
$(".panel-collapse").mouseleave(function(){
$(".panel-collapse").fadeOut();
});
With this the panel only close when mouse leaves the panel body.
Fiddle with mouseenter
You can combine js hover event and collapse bootstrap methods as events too.
If i understood your question correctly.

Using jquery to toggle div when parent div is visible

I have several parent div tags with same class which contain two children divs one of which is hidden. Only one parent is shown at a time. I have a button which moves through the parent one at a time by show the next and hiding the previous. A second button has to toggle the two children divs of a parent when its visible, it however only works for the first parent and not the others.. pls sample html below.. help is much appreciated.. Thanks
<div class="parent" >
<div id="child1"> text </div>
<div id="child2" style="display:none"> text </div>
</div>
<div class="parent" style="display:none" >
<div id="child1"> text </div>
<div id="child2" style="display:none"> text </div>
</div>
<div class="parent" style="display:none" >
<div id="child1"> text </div>
<div id="child2" style="display:none"> text </div>
</div>
scripts to move through parent :
$(function () {
$(".parent:first").fadeIn(); // show first step
$("#next-step").val('Continue');
$("#back-step").hide().click(function () {
var $step = $(".parent:visible");
if ($step.prev().hasClass("parent")) { // is there any previous step?
$step.hide().prev().fadeIn(); // show it and hide current step
}
});
$("#next-step").click(function () {
var $step = $(".parent:visible");
if ($step.next().hasClass("parent")) {
$step.hide().next().fadeIn();
$("#back-step").show(); // recall to show backStep button
}
else { // this is last step, submit form
//$("#next-step").hide();
$("form").submit();
}
});
});
script for button to toggle children for each current visible parent div
$('.txtFlip').on('click', function(event) {
$('.parent:visible > #child1').slideToggle();
$('.parent:visible > #child2').slideToggle();
});
My problem now is the script to toggle child1 and child2 for each current visible parent. It only works for the first parent but not the rest. Help plz...
Thanks......
You can use jQuery's :visible selector to pick which element is currently visible and toggle based on that.
bindLoopThrough = function($button, initial_selector){
// Define a function that will apply for both sets of buttons,
// because they have similar functionality
$button.on("click", function(){
var $current = $(initial_selector),
$next = $current.next();
if($next.length===0){
$next = $current.siblings().eq(0); // Reached end, get first.
}
$current.hide();
$next.show();
});
}
bindLoopThrough($("#button1"), ".parent:visible");
bindLoopThrough($("#button2"), ".parent:visible .child:visible");

Categories