How to set ScrollToTop Button to be active on viewport height? - css

At the moment i am using hardcoded height point to trigger visible ScrollToTop Button.
i would love to get solution to be triggered when passing viewport height.
const { scrollDirection } = useScrollDirection()
const { scrollPosition } = useScrollPosition()
const [isVisible, setIsVisible] = useState(false)
const toggleVisible = () => {
if (scrollPosition === 0) {
setIsVisible(false)
}
**if (scrollPosition > 800) {
setIsVisible(true)
} else if (scrollPosition <= 799) {
setIsVisible(false)
}**
}
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
})
}
window.addEventListener("scroll", toggleVisible)

you can use window.innerHeight
const toggleVisible = () => {
const viewportHeight = window.innerHeight;
if (scrollPosition === 0) {
setIsVisible(false)
}
**if (scrollPosition > viewportHeight) {
setIsVisible(true)
} else if (scrollPosition <= viewportHeight) {
setIsVisible(false)
}**
}

You can do this by using Intersection Observer (IO)
First you create an element that is just below the viewport initially. And whenever this element comes into view, show the button.
This requires one dummy element which you observe, for the demo I set the html element to position: relative for it to work. Maybe you can use a different element structure, based on your html. Important thing is that you have one element you can observe and trigger the element depending on when it comes into view.
let options = {
rootMargin: '0px',
threshold: 0.1 // when at least 10% of the element is visible we show the button
}
const callback = (entries, observer) => {
const btn = document.querySelector('#scroll-top');
entries.forEach(entry => {
if (entry.intersectionRatio > 0.1) {
// if we are past our 0.1 threshold we show the button
btn.classList.add('visible')
} else {
// otherwise we hide the button
btn.classList.remove('visible')
}
});
};
const observer = new IntersectionObserver(callback, options);
const target = document.querySelector('#button-trigger');
observer.observe(target);
.dummy-viewport {
min-height: 400vh;
}
html {
position: relative;
}
#button-trigger {
position: absolute;
top: 100vh;
left: 10px;
height: calc(100% - 100vh);
/* for demo purposes, don't show the element on the finished site*/
width: 2rem;
outline: 1px solid rebeccapurple;
writing-mode: vertical-rl;
text-orientation: mixed;
}
p {
padding: 0;
margin: 0;
}
#scroll-top {
position: fixed;
bottom: 40px;
right: 10px;
opacity: 0;
transition: .5s opacity;
}
#scroll-top.visible {
opacity: 1
}
<div class="dummy-viewport">
<p> Scroll down ↓ </p>
<button id="scroll-top" type="button"> Scroll to top </button>
</div>
<div id="button-trigger">
<p> When I am visible, I show the button </p>
</div>

Related

How to make the color of a div change permanently after it has been clicked in react.js

This is the grid that I have
Once a square has been clicked, the color changes to red. - This is done using active class
I would like the change to the background color of the div tag to remain permanent after the square has been clicked.
Code
Board.js
{board.map((row, rowIdx) => (
<div key={rowIdx} className="row">
{row.map((cell, cellIdx) => (
<div key={cellIdx} className="cell"></div>
))}
</div>
))}
Board.css
.row {
height: 30px;
margin: 10px;
transition: transform 0.1s;
}
.cell:hover {
transform: scale(1.4);
}
.cell {
width: 30px;
height: 30px;
outline: 1px solid rgb(134, 154, 189);
display: inline-block;
background-color: seagreen;
margin: 5px;
transition: transform 0.2s;
}
.row :active {
background-color: red;
}
.cell :active { // Does not do anything
background-color: blue;
}
Once another square is clicked, the previosly clicked one does not remain active, you can do this by adding another class with your desired style, and using state to track the squares that have been clicked.
const [boardIndeces, setBoardIndeces] = useState(initArray(board));
const initArray = arr => {
let rows = [];
for (let i = 0; i < arr.length; i++) {
let row = [];
const currBoard = arr[i];
for (let z = 0; z < currBoard.length; z++) {
row[z] = false;
}
rows[i] = row;
}
return rows;
};
const onCellClick = (rowIdx, cellIdx) => {
if (!(boardIndeces[rowIdx] && boardIndeces[rowIdx][cellIdx])) {
boardIndeces[rowIdx][cellIdx] = true;
setBoardIndeces([...boardIndeces]);
}
};
{
board.map((row, rowIdx) => (
<div key={rowIdx}>
{row.map((cell, cellIdx) => (
<div
key={cellIdx}
className={
boardIndeces[rowIdx].includes(cellIdx)
? 'your_active_class'
: 'your_inactive_class'
}
onClick={() => onCellClick(rowIdx, cellIdx)}
></div>
))}
</div>
));
}
You can use a checkbox if you don't want to use React
HTML
<input type="checkbox" id="color" name="color">
<label id="color-div" for="color">
<!-- the div you want to change color -->
</label>
CSS
#color {
display: none
}
#color:checked + #color-div { /* + in CSS is the sibling combinator */
background-color: #fffff /* your background color */
}
What you're basically doing is making an invisible checkbox and toggling it with the label, when it's toggled you do the changes to the CSS
Remember the CSS combinators only work in elements after the HTML element it's being applied to

How to run more than one css transition with a click on a button?

I am building an animated hamburger menu with html css js. I now know how to start a css transition with javascript. See https://jsfiddle.net/ralphsmit/byaLfox5/. My problem now is that I need to run more than one transition with a click on my button. I've put my code here https://jsfiddle.net/ralphsmit/v980ouwj/16/.
A short explanation of my code. I have made a button (for the sake of clarity I made it green with a low opacity) and when that button is clicked, the background .dsgn-header-background will appear. Now I also want the two rectangle for the menu to animate into a cross and that the the .dsgn-header-menu-opened-menuitems also fade in.
My question is, how do I modify this js code, so that more than one transition will be started? So all transitions are a different element. You'll find the full code in the JS fiddle above (feel free to edit this).
Javascript:
const background = document.querySelector('.dsgn-header-background');
const button = document.querySelector('.dsgn-header-button');
let open = false;
button.addEventListener('click', onClickPlay);
function onClickPlay(){
if(background.classList.contains('on')){
background.classList.remove('on');
}else{
background.classList.add('on');
}
}
Check this out.
function onClickPlay(){
if(background.classList.contains('on')){
background.classList.remove('on');
element.classList.remove('anotherClassWithDifferentTransitions');
}else{
background.classList.add('on');
element.classList.add('anotherClassWithDifferentTransitions');
}
}
Cheers!
You can try this , The changes is i have added 2 more constant variable which adding on class when menu open and remove on class when menu closes.
const background = document.querySelector('.dsgn-header-background');
const button = document.querySelector('.dsgn-header-button');
const menu_up = document.querySelector('.dsgn-header-rectangle-up');
const menu_down = document.querySelector('.dsgn-header-rectangle-down');
let open = false;
button.addEventListener('click', onClickPlay);
function onClickPlay(){
if(background.classList.contains('on')){
background.classList.remove('on');
menu_up.classList.remove('on');
menu_down.classList.remove('on');
}else{
background.classList.add('on');
menu_up.classList.add('on');
menu_down.classList.add('on');
}
}
hope this will help you .
const content = document.querySelector('.content');
const button = document.querySelector('.dsgn-header-button');
function onClickPlay() {content.classList.toggle('on');}
button.addEventListener('click', onClickPlay);
fiddle: https://jsfiddle.net/s24mbakf/
Add the other elements to your onClickPlay function as you did with demo.
const demo = document.querySelector('.demo');
const demo2 = document.querySelector('.demo2');
const buttondemo = document.querySelector('.buttondemo');
let open = false;
buttondemo.addEventListener('click', onClickPlay);
function onClickPlay(){
if(demo.classList.contains('on')){
demo.classList.remove('on');
demo2.classList.remove('on');
} else {
demo.classList.add('on');
demo2.classList.add('on');
}
}
.demo {
width: 0;
height: 100vh;
background-color: black;
position: absolute;
right: 0;
transition: width 4s;
}
.demo.on {
width: 100vw;
}
.demo2 {
width: 0;
height: 50vh;
background-color: red;
position: absolute;
right: 0;
transition: width 8s;
}
.demo2.on {
width: 100vw;
background-color: yellow;
}
.buttondemo {
position: absolute;
top: 0px;
right: 0px;
width: 100px;
height: 100px;
background-color: green;
}
<div class="demo"><div>
<div class="demo2"><div>
<div class="buttondemo"><div>

section content scaling with background

I am trying to stop my section content from scaling with my section background. the scale of the background is perfect but it seems to make the content scale also, I am using gsap library I have tried creating a container inside the section and give it absolute but nothing I do stops the content inside from scaling
//First the variables our app is going to use need to be declared
//References to DOM elements
var $window = $(window);
var $document = $(document);
//Only links that starts with #
var $navButtons = $("nav a").filter("[href^=#]");
var $navGoPrev = $(".go-prev");
var $navGoNext = $(".go-next");
var $sectionsContainer = $(".sections-container");
var $sections = $(".section");
var $currentSection = $sections.first();
//Animating flag - is our app animating
var isAnimating = false;
//The height of the window
var pageHeight = $window.innerHeight();
//Key codes for up and down arrows on keyboard. We'll be using this to navigate change sections using the keyboard
var keyCodes = {
UP : 38,
DOWN: 40
}
//Going to the first section
goToSection($currentSection);
/*
* Adding event listeners
* */
$window.on("resize", onResize).resize();
$window.on("mousewheel DOMMouseScroll", onMouseWheel);
$document.on("keydown", onKeyDown);
$navButtons.on("click", onNavButtonClick);
$navGoPrev.on("click", goToPrevSection);
$navGoNext.on("click", goToNextSection);
/*
* Internal functions
* */
/*
* When a button is clicked - first get the button href, and then section to the container, if there's such a container
* */
function onNavButtonClick(event)
{
//The clicked button
var $button = $(this);
//The section the button points to
var $section = $($button.attr("href"));
//If the section exists, we go to it
if($section.length)
{
goToSection($section);
event.preventDefault();
}
}
/*
* Getting the pressed key. Only if it's up or down arrow, we go to prev or next section and prevent default behaviour
* This way, if there's text input, the user is still able to fill it
* */
function onKeyDown(event)
{
var PRESSED_KEY = event.keyCode;
if(PRESSED_KEY == keyCodes.UP)
{
goToPrevSection();
event.preventDefault();
}
else if(PRESSED_KEY == keyCodes.DOWN)
{
goToNextSection();
event.preventDefault();
}
}
/*
* When user scrolls with the mouse, we have to change sections
* */
function onMouseWheel(event)
{
//Normalize event wheel delta
var delta = event.originalEvent.wheelDelta / 30 || -event.originalEvent.detail;
//If the user scrolled up, it goes to previous section, otherwise - to next section
if(delta < -1)
{
goToNextSection();
}
else if(delta > 1)
{
goToPrevSection();
}
event.preventDefault();
}
/*
* If there's a previous section, section to it
* */
function goToPrevSection()
{
if($currentSection.prev().length)
{
goToSection($currentSection.prev());
}
}
/*
* If there's a next section, section to it
* */
function goToNextSection()
{
if($currentSection.next().length)
{
goToSection($currentSection.next());
}
}
/*
* Actual transition between sections
* */
function goToSection($section)
{
//If the sections are not changing and there's such a section
if(!isAnimating && $section.length)
{
//setting animating flag to true
isAnimating = true;
//Sliding to current section
TweenLite.set($currentSection, {autoAlpha: 0, display: 'none'});
$currentSection = $section;
TweenLite.set($currentSection, {display: 'block'});
TweenLite.fromTo($currentSection, 0.6, {scale: 0.9, autoAlpha: 0}, {scale: 1, autoAlpha: 1, ease: Power1.easeOut, onComplete: onSectionChangeEnd, onCompleteScope: this});
//Animating menu items
TweenLite.to($navButtons.filter(".active"), 0.5, {className: "-=active"});
TweenLite.to($navButtons.filter("[href=#" + $currentSection.attr("id") + "]"), 0.5, {className: "+=active"});
}
}
/*
* Once the sliding is finished, we need to restore "isAnimating" flag.
* You can also do other things in this function, such as changing page title
* */
function onSectionChangeEnd()
{
isAnimating = false;
}
/*
* When user resize it's browser we need to know the new height, so we can properly align the current section
* */
function onResize(event)
{
//This will give us the new height of the window
var newPageHeight = $window.innerHeight();
/*
* If the new height is different from the old height ( the browser is resized vertically ), the sections are resized
* */
if(pageHeight !== newPageHeight)
{
pageHeight = newPageHeight;
//This can be done via CSS only, but fails into some old browsers, so I prefer to set height via JS
TweenLite.set([$sectionsContainer, $sections], {height: pageHeight + "px"});
//The current section should be always on the top
TweenLite.set($sectionsContainer, {scrollTo: {y: pageHeight * $currentSection.index() }});
}
}
body, div, p {
margin: 0;
padding: 0;
}
body {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 300;
letter-spacing: 0.0625em;
background-color: #000;
}
h1{
color: #fff;
}
.sections-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 10;
}
.section {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
display: none;
visibility: hidden;
opacity: 0;
}
#section-1 {
display: block;
visibility: visible;
opacity: 1;
}
.section .centered h1 {
text-align: center;
}
.section .centered p {
text-align: center;
}
#section-1 {
background-color: #5A4748;
}
#section-2 {
background-color: #45959b;
}
#section-3 {
background-color: #778899;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenLite.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/ScrollToPlugin.min.js"></script>
<div class="sections-container">
<div class="section" id="section-1">
<div class="centered">
<h1>1</h1>
</div>
</div>
<div class="section" id="section-2">
<div class="centered">
<h1>2</h1>
</div>
</div>
<div class="section" id="section-3">
<div class="centered">
<h1>3</h1>
</div>
</div>
</div>
Would this be what you're looking for? I basically added a background div
<div id="background"></div>
#background {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
visibility: visible;
opacity: 1;
}
which is assigned a background class based on the section which is currently visible.
var $background = $("#background");
...
$background.classList = "";
TweenLite.set($background, {
className: '+=bg-' + ($sections.index($currentSection) + 1)
});
TweenLite.fromTo($background, 0.6, {
scale: 0.9,
autoAlpha: 0
}, {
scale: 1,
autoAlpha: 1,
ease: Power1.easeOut,
onComplete: onSectionChangeEnd,
onCompleteScope: this
});
You can choose to remove the autoAlpha tween on the section numbers if you so prefer.
//First the variables our app is going to use need to be declared
//References to DOM elements
var $window = $(window);
var $document = $(document);
//Only links that starts with #
var $navButtons = $("nav a").filter("[href^=#]");
var $navGoPrev = $(".go-prev");
var $navGoNext = $(".go-next");
var $sectionsContainer = $(".sections-container");
var $sections = $(".section");
var $background = $("#background");
var $currentSection = $sections.first();
//Animating flag - is our app animating
var isAnimating = false;
//The height of the window
var pageHeight = $window.innerHeight();
//Key codes for up and down arrows on keyboard. We'll be using this to navigate change sections using the keyboard
var keyCodes = {
UP: 38,
DOWN: 40
}
//Going to the first section
goToSection($currentSection);
/*
* Adding event listeners
* */
$window.on("resize", onResize).resize();
$window.on("mousewheel DOMMouseScroll", onMouseWheel);
$document.on("keydown", onKeyDown);
$navButtons.on("click", onNavButtonClick);
$navGoPrev.on("click", goToPrevSection);
$navGoNext.on("click", goToNextSection);
/*
* Internal functions
* */
/*
* When a button is clicked - first get the button href, and then section to the container, if there's such a container
* */
function onNavButtonClick(event) {
//The clicked button
var $button = $(this);
//The section the button points to
var $section = $($button.attr("href"));
//If the section exists, we go to it
if ($section.length) {
goToSection($section);
event.preventDefault();
}
}
/*
* Getting the pressed key. Only if it's up or down arrow, we go to prev or next section and prevent default behaviour
* This way, if there's text input, the user is still able to fill it
* */
function onKeyDown(event) {
var PRESSED_KEY = event.keyCode;
if (PRESSED_KEY == keyCodes.UP) {
goToPrevSection();
event.preventDefault();
} else if (PRESSED_KEY == keyCodes.DOWN) {
goToNextSection();
event.preventDefault();
}
}
/*
* When user scrolls with the mouse, we have to change sections
* */
function onMouseWheel(event) {
//Normalize event wheel delta
var delta = event.originalEvent.wheelDelta / 30 || -event.originalEvent.detail;
//If the user scrolled up, it goes to previous section, otherwise - to next section
if (delta < -1) {
goToNextSection();
} else if (delta > 1) {
goToPrevSection();
}
event.preventDefault();
}
/*
* If there's a previous section, section to it
* */
function goToPrevSection() {
console.log($currentSection.prev().length > 0);
if ($currentSection.prev().length) {
goToSection($currentSection.prev());
}
}
/*
* If there's a next section, section to it
* */
function goToNextSection() {
if ($currentSection.next().length > 0) {
goToSection($currentSection.next());
}
}
/*
* Actual transition between sections
* */
function goToSection($section) {
//If the sections are not changing and there's such a section
if (!isAnimating && $section.length) {
//setting animating flag to true
isAnimating = true;
//Sliding to current section
TweenLite.set($currentSection, {
autoAlpha: 0,
display: 'none'
});
$currentSection = $section;
$background.classList = "";
TweenLite.set($currentSection, {
display: 'block'
});
TweenLite.set($background, {
className: 'bg-' + ($sections.index($currentSection) + 1)
});
//console.log($sections.index($currentSection) + 1);
TweenLite.fromTo($background, 0.6, {
scale: 0.9,
autoAlpha: 0
}, {
scale: 1,
autoAlpha: 1,
ease: Power1.easeOut,
onComplete: onSectionChangeEnd,
onCompleteScope: this
});
TweenLite.fromTo($currentSection, 0.6, {
autoAlpha: 0
}, {
autoAlpha: 1,
ease: Power1.easeOut,
});
//Animating menu items
TweenLite.to($navButtons.filter(".active"), 0.5, {
className: "-=active"
});
TweenLite.to($navButtons.filter("[href=#" + $currentSection.attr("id") + "]"), 0.5, {
className: "+=active"
});
}
}
/*
* Once the sliding is finished, we need to restore "isAnimating" flag.
* You can also do other things in this function, such as changing page title
* */
function onSectionChangeEnd() {
isAnimating = false;
}
/*
* When user resize it's browser we need to know the new height, so we can properly align the current section
* */
function onResize(event) {
//This will give us the new height of the window
var newPageHeight = $window.innerHeight();
/*
* If the new height is different from the old height ( the browser is resized vertically ), the sections are resized
* */
if (pageHeight !== newPageHeight) {
pageHeight = newPageHeight;
//This can be done via CSS only, but fails into some old browsers, so I prefer to set height via JS
TweenLite.set([$sectionsContainer, $sections], {
height: pageHeight + "px"
});
//The current section should be always on the top
TweenLite.set($sectionsContainer, {
scrollTo: {
y: pageHeight * $currentSection.index()
}
});
}
}
body,
div,
p {
margin: 0;
padding: 0;
}
body {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 300;
letter-spacing: 0.0625em;
background-color: #000;
}
h1 {
color: #fff;
}
.sections-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 10;
}
.section {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
display: none;
visibility: hidden;
opacity: 0;
}
#section-1 {
display: block;
visibility: visible;
opacity: 1;
}
.section .centered h1 {
text-align: center;
}
.section .centered p {
text-align: center;
}
#background {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
visibility: visible;
opacity: 1;
}
.bg-1 {
background-color: #5A4748;
}
.bg-2 {
background-color: #45959b;
}
.bg-3 {
background-color: #778899;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenLite.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/ScrollToPlugin.min.js"></script>
<div id="background"></div>
<div class="sections-container">
<div class="section" id="section-1">
<div class="centered">
<h1>1</h1>
</div>
</div>
<div class="section" id="section-2">
<div class="centered">
<h1>2</h1>
</div>
</div>
<div class="section" id="section-3">
<div class="centered">
<h1>3</h1>
</div>
</div>
</div>

Double scrollbar with shrinking toolbar

I am working on a photo gallery in AngularJS using Angular Material (run the snippet in fullscreen to see my problem).
var app = angular.module('app', ['ngMaterial']);
app.controller('TitleController', function($scope) {
$scope.title = 'Gallery';
});
app.controller('GalleryCtrl', function($scope, $http, $q, $mdMedia, $mdDialog) {
//https://material.angularjs.org/latest/demo/virtualRepeat
$scope.Images = [],
//add more images
$scope.LoadMore = function() {
for (i = 0; i < 25; i++) {
var randomWidth = Math.round(Math.random() * (800 - 400) + 400);
var randomHeight = Math.round(Math.random() * (800 - 400) + 400);
$scope.Images.push({
src: "http://placehold.it/" + randomWidth + "x" + randomHeight + "/",
id: Math.round(Math.random() * 10000)
});
};
}
$scope.ShowDetails = function(ev, number) {
var useFullScreen = ($mdMedia('sm') || $mdMedia('xs')) && $scope.customFullscreen;
$mdDialog.show({
controller: DialogController,
templateUrl: 'Home/GetInfo?id=' + number,
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose: true,
fullscreen: useFullScreen
})
$scope.$watch(function() {
return $mdMedia('xs') || $mdMedia('sm');
}, function(wantsFullScreen) {
$scope.customFullscreen = (wantsFullScreen === true);
});
};
function DialogController($scope, $mdDialog) {
$scope.hide = function() {
$mdDialog.hide();
};
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.answer = function(answer) {
$mdDialog.hide(answer);
};
}
//initial loading
$scope.LoadMore();
});
body {
background: #eeeeee;
}
html {
background: #eeeeee;
}
.gridListdemoBasicUsage md-grid-list {
margin: 8px;
}
.gridListdemoBasicUsage .green {
background: #b9f6ca;
}
.gridListdemoBasicUsage md-grid-tile {
transition: all 400ms ease-out 50ms;
}
.responsiveImage {
max-width: 100%;
max-height: 100%;
}
md-content {
background: #eeeeee;
position: relative;
}
.fit {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.toolbardemoScrollShrink .face {
width: 48px;
margin: 16px;
border-radius: 48px;
border: 1px solid #ddd;
}
.md-toolbar-tools {
background-color: #259b24;
}
.dialogdemoBasicUsage #popupContainer {
position: relative;
}
.dialogdemoBasicUsage .footer {
width: 100%;
text-align: center;
margin-left: 20px;
}
.dialogdemoBasicUsage .footer,
.dialogdemoBasicUsage .footer > code {
font-size: 0.8em;
margin-top: 50px;
}
.dialogdemoBasicUsage button {
width: 200px;
}
.dialogdemoBasicUsage div#status {
color: #c60008;
}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.7/angular-material.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular-animate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular-aria.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.7/angular-material.min.js"></script>
<body ng-app="app" ng-controller="GalleryCtrl as gc" ng-cloak="" id="popupContainer" class="gridListdemoBasicUsage dialogdemoBasicUsage">
<md-toolbar md-scroll-shrink="" ng-if="true" ng-controller="TitleController">
<div class="md-toolbar-tools">
<h3><span>{{title}}</span></h3>
</div>
</md-toolbar>
<md-content style="height:100vh" />
<md-grid-list md-cols-xs="1" md-cols-sm="2" md-cols-md="4" md-cols-gt-md="6" md-row-height-gt-md="1:1" md-row-height="2:2" md-gutter="12px" md-gutter-gt-sm="8px">
<md-grid-tile ng-click="ShowDetails($event, n.id)" ng-repeat="n in Images" class="green">
<img class="responsiveImage" src="{{n.src}}">
<md-grid-tile-footer>
<h3>Photo number {{n.id}}</h3>
</md-grid-tile-footer>
</md-grid-tile>
</md-grid-list>
<section layout="row" layout-sm="column" layout-align="center center" layout-wrap="">
<md-button class="md-raised md-primary" ng-click="LoadMore()">Primary</md-button>
</section>
</body>
Go fullscreen, scroll to the bottom of the page, and press a button to load more images. The problem I'm having: I am trying to get the toolbar at the top of the screen to disappear when scrolling down, and appear again when scrolling up. However, 2 scrollbars appear, and only the right one affects the toolbar.The left scrollbar actually scrolls all the way down on the page.
My desired situation: only 1 visible scrollbar to scroll down the entire gallery, that also makes the toolbar appear and disappear. How do I do this?
try adding overflow-y: hidden; to the body css rule.

jQuery UI Droppable block by absolute div

How can a jquery ui droppable be blocked by an overlaid div?
See this example: http://jsfiddle.net/JSFU4/3/. A red div is overlaying the droppable area; however, when dragging on top of this area, the droppable is still activated. How can this be avoided?
Html
<div>
<div class="drop">drop here</div>
</div>
<div>
<div class="drag">drag me</div>
</div>
<div class="overlay">i want to block the droppable</div>
CSS
.drag {
display: inline-block;
width: 100px;
height: 100px;
border: 1px solid black;
background-color: lightblue;
z-index: 1;
}
.drop {
display: inline-block;
border: 1px dotted black;
width: 200px;
height: 200px;
}
.drop-hover {
background-color: grey;
}
.overlay {
position: absolute;
width: 300px;
height: 100px;
top: 50px;
background-color: red;
border: 1px solid black;
}
JS
$(function () {
$('.drag').draggable();
$('.drop').droppable({
tolerance: 'pointer',
hoverClass: 'drop-hover'
});
});
I don't think there is anything out of box to achieve this. You need to do some kind of collision detection and then do your logic accordingly. I have done a POC for you.
DEMO
var drag = $('.drag');
var overlay = $('.overlay');
$(function () {
$('.drag').draggable();
$('.drop').droppable({
tolerance: 'pointer',
hoverClass: 'drop-hover'
});
});
var int = self.setInterval(function () {
if (overlaps(drag, overlay)) {
$('.drop').css('visibility', 'hidden');
} else {
$('.drop').css('visibility', 'visible');
}
}, 100);
var overlaps = (function () {
function getPositions(elem) {
var pos, width, height;
pos = $(elem).position();
width = $(elem).width() / 2;
height = $(elem).height();
return [[pos.left, pos.left + width], [pos.top, pos.top + height]];
}
function comparePositions(p1, p2) {
var r1, r2;
r1 = p1[0] < p2[0] ? p1 : p2;
r2 = p1[0] < p2[0] ? p2 : p1;
return r1[1] > r2[0] || r1[0] === r2[0];
}
return function (a, b) {
var pos1 = getPositions(a),
pos2 = getPositions(b);
return comparePositions(pos1[0], pos2[0]) && comparePositions(pos1[1], pos2[1]);
};
})();
The code above detects the collision between two DIVs and returns true or false.

Resources