Angular Material Design collapsible sidenav - sidebar

I am trying to implement angular material designs sidenav and I've got it to work correctly but I wanted to create a sidenav as shown below,
and on mouse over expands to this
I tried using two sidenav bars and on mouseover show one and hide the other but that din't work as expected.Would be glad if you could help me out here.
EDIT
index.html
<div layout="row" flex>
<md-sidenav layout="column" class="md-sidenav-left md-whiteframe-z2" md-component-id="small" md-is-locked-open="$mdMedia('gt-sm')" ng-mouseover="hoverIn()" ng-mouseout="hoverOut()">
</md-sidenav>
<md-sidenav flex layout="column" class="rightnav md-whiteframe-z2" ng-show="hoverEdit" md-component-id="big" md-is-locked-open="$mdMedia('gt-sm')">
</md-sidenav>
<div layout="column" flex id="content">
<md-content layout="column" flex class="md-padding">
</md-content>
</div>
</div>
app.js
app.controller('AppCtrl', ['$scope', '$mdSidenav', function($scope,$mdSidenav){
$scope.edit = true;
$scope.hoverEdit = false;
$scope.toggleSidenav = function(menuId) {
$scope.hoverEdit = true;
$mdSidenav(menuId).toggle();
};
$scope.hoverIn = function(){
$scope.hoverEdit = true;
$scope.edit = false;
};
$scope.hoverOut = function(){
$scope.hoverEdit = false;
$scope.edit = true;
};
}]);
main.css
md-sidenav.md-locked-open.rightnav,
md-sidenav.md-locked-open-remove.md-closed.rightnav,
md-sidenav.md-locked-open.md-closed.rightnav,
md-sidenav.md-locked-open.md-closed.rightnav
{
min-width: 200px !important;
width: auto !important;
max-width: 700px !important;
background-color: #10123B;
border-left: 2px solid #38ddcc;
height : 100%;
position: absolute;
}
md-sidenav.md-locked-open,
md-sidenav.md-locked-open-remove.md-closed,
md-sidenav.md-locked-open.md-closed,
md-sidenav.md-locked-open.md-closed.md-sidenav-left
{
min-width: 50px !important;
width: auto !important;
max-width: 700px !important;
background-color: #10123B;
border-left: 2px solid #38ddcc;
height : 100%;
position: absolute;
}

I am Completed the AngularJS Sidenav as the Above Image...
And the Codes are Given Below...
index.html:
<div ng-controller="mainCtrl">
<md-toolbar layout="column" ><span flex="flex">
<div class="md-toolbar-tools">
</div>
</md-toolbar>
<md-content>
<div layout="row" >
<div ng-mouseenter="hoverIn()" ng-mouseleave="hoverOut()" >
<md-sidenav style="position: fixed;" layout="column" ng-class="myClass " md-component-id="small" md-is-locked-open=true >
<md-toolbar md-whiteframe="3" >
<div class="md-toolbar-tools">
<img src="https://www.atlanticaviation.com/docs/default-source/logos-library/atlantic-logo-4c-a2.png?sfvrsn=12" height="30" width="40" />
</div>
</md-toolbar>
</md-sidenav>
<md-sidenav flex layout="column" class="rightnav md-whiteframe-z2" ng-show="hoverEdit" md-component-id="big" style="position: fixed;" ng-hide=true md-is-locked-open=true>
<md-toolbar md-whiteframe="3">
<div class="md-toolbar-tools">
<img src="https://www.atlanticaviation.com/docs/default-source/logos-library/atlantic-logo-4c-a2.png?sfvrsn=12" height="30" width="50" />
<h5 style="color: #fff;">ARAVINTHAN MENU</h5>
<md-button ng-click="toggleClass()" class="cmn-toggle-switch cmn-toggle-switch__htra ">
Toggle
</button>
</div>
</md-toolbar>
</md-sidenav>
</div>
<md-content flex>
</md-content>
</div>
</md-content>
</div>
Style.css :
/*CSS Styles for the Sidenav Bar */
.rightnav
{
min-width: 200px !important;
width: 280px !important;
max-width: 700px !important;
height: 100%;
position: fixed;
box-sizing: border-box;
z-index: 60;
bottom: 0;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.md-sidenav-opened
{
min-width: 200px !important;
width: 280px !important;
max-width: 700px !important;
border: 1px solid #ddd;
}
.md-sidenav-left
{
min-width: 55px !important;
width: 55px !important;
max-width: 700px !important;
overflow-x:hidden;
}
App.js
//JS Code for Side Nav here
angular.module('anApp', ['ngMaterial'])
.controller('mainCtrl',['$scope', '$mdSidenav', function($scope,$mdSidenav)
{
$scope.myClass = "md-sidenav-left md-whiteframe-z2";
$scope.option1 = "md-sidenav-opened md-whiteframe-z2";
$scope.toggleFlag= true;
$scope.edit = true;
$scope.hoverEdit = false;
$scope.size = "5";
$scope.toggleClass = function() {
if( $scope.myClass == "md-sidenav-left md-whiteframe-z2" )
{
$scope.myClass = "md-sidenav-opened md-whiteframe-z2";
$scope.toggleFlag = false;
$scope.size = "25";
}
else
{
$scope.myClass = "md-sidenav-left md-whiteframe-z2";
$scope.toggleFlag = true;
$scope.size = "5";
}
}
$scope.toggleSidenav = function(menuId) {
$scope.hoverEdit = true;
};
$scope.hoverIn = function(){
if($scope.toggleFlag)
{
$scope.hoverEdit = true;
$scope.edit = false;
}
};
$scope.hoverOut = function(){
if($scope.toggleFlag)
{
$scope.hoverEdit = false;
$scope.edit = true;
}
};
}]);
The Codepen Example - Codepen

Related

HTML - Resize multiple divs and their content

I am looking to create a bottom pannel with a resizable height. The top pannel consists of 2 divs with a resizable width. I was able to follow this https://htmldom.dev/create-resizable-split-views/ , but the vertical resizing is not resizing the contents of the two top divs. How can I fill the contents of the top container with the contents of the two Divs, to ensure that they resize when the bottom pannel is dragged up?
In other words, I'm looking for two top horizontally resizable pannels and one bottom pannel vertically resizable from them, while shrinking/expanding the contents during resize.
Edit: The bottom container needs to be set on all tabs and show up under all tab content on the page.
<div class="container">
<div class = "container__top">
<div class="tab-content" >
<body class="noscroll">
<div class="Tab1">
<div class="main-body">
<div class="page-wrapper">
<div class="row">
<div class="col-sm-12">
<div class="container__left">
STUFF</div>
<div class="resizer" data-direction="horizontal"></div>
<div class="container__right">
STUFF</div>
</div>
</div>
</div>
</div>
<div class="Tab2"></div>
</body>
</div>
</div>
<div class="resizer" data-direction="vertical"></div>
<div class = "container__bottom">
STUFF</div>
You could try something like this. You'll have to be explicit for a few things, like parent height and the min/max heights for top and bottom sections, but this could be a decent start. It's ugly, sorry.
edit: it's still ugly, and you'll have to fix up the tab/hide function for more tabs, but this works as intended as far as I can tell.
document.addEventListener('DOMContentLoaded', function() {
const resizable = function(resizer) {
const direction = resizer.getAttribute('data-direction') || 'horizontal';
const prevSibling = resizer.previousElementSibling;
const nextSibling = resizer.nextElementSibling;
// The current position of mouse
let x = 0;
let y = 0;
let prevSiblingHeight = 0;
let prevSiblingWidth = 0;
// Handle the mousedown event
// that's triggered when user drags the resizer
const mouseDownHandler = function(e) {
// Get the current mouse position
x = e.clientX;
y = e.clientY;
const rect = prevSibling.getBoundingClientRect();
prevSiblingHeight = rect.height;
// Attach the listeners to `document`
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
const mouseMoveHandler = function(e) {
// How far the mouse has been moved
const dx = e.clientX - x;
const dy = e.clientY - y;
const parentHeight = resizer.parentNode.getBoundingClientRect().height;
const h = (prevSiblingHeight + dy)
prevSibling.style.height = `${h}px`;
nextSibling.style.height = `${parentHeight - h}px`;
const cursor = 'row-resize';
resizer.style.cursor = cursor;
document.body.style.cursor = cursor;
prevSibling.style.userSelect = 'none';
prevSibling.style.pointerEvents = 'none';
nextSibling.style.userSelect = 'none';
nextSibling.style.pointerEvents = 'none';
};
const mouseUpHandler = function() {
resizer.style.removeProperty('cursor');
document.body.style.removeProperty('cursor');
prevSibling.style.removeProperty('user-select');
prevSibling.style.removeProperty('pointer-events');
nextSibling.style.removeProperty('user-select');
nextSibling.style.removeProperty('pointer-events');
// Remove the handlers of `mousemove` and `mouseup`
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};
// Attach the handler
resizer.addEventListener('mousedown', mouseDownHandler);
};
// Query all resizers
document.querySelectorAll('.resizer').forEach(function(ele) {
resizable(ele);
});
// Query the element
const horizontalResizer = document.getElementById('dragMeHorizontal');
const leftSide = horizontalResizer.previousElementSibling;
const rightSide = horizontalResizer.nextElementSibling;
// The current position of mouse
let x = 0;
let y = 0;
let leftWidth = 0;
// Handle the mousedown event
// that's triggered when user drags the resizer
const mouseDownHandler = function(e) {
// Get the current mouse position
x = e.clientX;
y = e.clientY;
leftWidth = leftSide.getBoundingClientRect().width;
// Attach the listeners to `document`
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
const mouseMoveHandler = function(e) {
// How far the mouse has been moved
const dx = e.clientX - x;
const dy = e.clientY - y;
const newLeftWidth = ((leftWidth + dx) * 100) / horizontalResizer.parentNode.getBoundingClientRect().width;
leftSide.style.width = `${newLeftWidth}%`;
horizontalResizer.style.cursor = 'col-resize';
document.body.style.cursor = 'col-resize';
leftSide.style.userSelect = 'none';
leftSide.style.pointerEvents = 'none';
rightSide.style.userSelect = 'none';
rightSide.style.pointerEvents = 'none';
};
const mouseUpHandler = function() {
horizontalResizer.style.removeProperty('cursor');
document.body.style.removeProperty('cursor');
leftSide.style.removeProperty('user-select');
leftSide.style.removeProperty('pointer-events');
rightSide.style.removeProperty('user-select');
rightSide.style.removeProperty('pointer-events');
// Remove the handlers of `mousemove` and `mouseup`
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};
// Attach the handler
horizontalResizer.addEventListener('mousedown', mouseDownHandler);
});
// Tab Changer
function changeActiveTab(tabNumber) {
const allOtherTabs = document.getElementsByClassName("tab")
const hideElements = [...allOtherTabs].filter((element, index) => index !== tabNumber)
const selectedTab = document.getElementsByClassName("tab")[tabNumber]
hideElements.forEach(element => element.classList.add("hidden"));
selectedTab.classList.remove("hidden");
}
// handle tab 1 select
document.getElementById("tab1").addEventListener('mousedown', () => {
changeActiveTab(0)
})
// handle tab 2 select
document.getElementById("tab2").addEventListener('mousedown', () => {
changeActiveTab(1)
})
// handle tab 3 select
document.getElementById("tab3").addEventListener('mousedown', () => {
changeActiveTab(2)
})
.resizer[data-direction='vertical'] {
background-color: #cbd5e0;
cursor: ns-resize;
height: 10px;
width: 100%;
}
.button__container {
margin: 6px 12px;
display: flex;
flex-direction: row;
}
.tab__internal {
max-height: 18%;
}
button {
background-color: orange;
border: none;
padding: 8px;
min-width: 150px;
margin: 1px;
border: 1px solid teal;
}
.main__container {
display: flex;
flex-direction: column;
justify-content: center;
border: 1px solid blue;
}
.sub__container {
height: 250px;
/* Misc */
}
#tab__2 {
background-color: green;
}
#tab__3 {
background-color: teal;
}
.container__top {
/* Initial height */
height: 100%;
/* Misc */
display: flex;
flex-direction: row;
background-color: green;
}
.hidden {
display: none;
}
.tabs__container {
background-color: blue;
height: 100px;
max-height: calc(100% - 100px);
min-height: 50px;
}
.tab__contents {
height: 100%;
}
.container__bottom {
/* Take the remaining height */
width: 100%;
height: 150px;
min-height: 100px;
max-height: calc(100% - 50px);
/* Misc */
display: flex;
flex-direction: column;
background-color: red;
}
.container__left {
width: 50%;
height: 100%;
/* Misc */
display: flex;
background-color: goldenrod;
}
.resizer__horizontal {
background-color: #cbd5e0;
cursor: ew-resize;
height: 100%;
width: 5px;
}
.container__right {
/* Take the remaining width */
flex: 1;
height: 100%;
/* Misc */
display: flex;
background-color: purple;
}
<html lang="en">
<head>
<meta charset="utf-8" />
<title>HTML DOM - Create resizable split views</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/css/demo.css" />
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter&family=Source+Code+Pro&display=swap" />
</head>
<body>
<div class="main__container">
<h3>Main Container</h3>
<div class="button__container">
<button class="tab_selector" id="tab1">Tab 1</button>
<button class="tab_selector" id="tab2">Tab 2</button>
<button class="tab_selector" id="tab3">Tab 3</button>
</div>
</div>
<div class="sub__container">
<div class="tabs__container">
<div class="container__top tab" id="tab__1">
<div class="container__left">
<div class="tab__contents">
<div class="tab__internal">stuff</div>
<div class="tab__internal">stuff</div>
<div class="tab__internal">stuff</div>
<div class="tab__internal">stuff</div>
</div>
</div>
<div class="resizer__horizontal" id="dragMeHorizontal"></div>
<div class="container__right tab__contents">Right</div>
</div>
<div class="container__top tab hidden" id="tab__2">
<div class="tab-contents">Tab 2</div>
</div>
<div class="container__top tab hidden" id="tab__3">
<div class="tab-contents">Tab </div>
</div>
</div>
<div class="resizer" data-direction="vertical"></div>
<div class="container__bottom">
<h4>Bottom</h4>
<p>Stuff up in here.</p>
</div>
</div>
</body>
</html>

On scroll horizontal content in Angular 10

I am trying to create a horizontal scroll on mouse wheel. when I scrolled content1 to content got stuck and when I move the up the scroll it worked properly.
please check on the link and give the solution as soon as possible.
here is the stackblitz demo link
Please help me with what can I do that.
#ViewChild('horizon') horizon: ElementRef;
#ViewChild('horizon1') horizon1: ElementRef;
#ViewChild('horizon2') horizon2: ElementRef;
#ViewChild('horizon3') horizon3: ElementRef;
#ViewChild('horizon4') horizon4: ElementRef;
#ViewChild('scrollPoint') scrollPoint: ElementRef;
#HostListener('mousewheel', ['$event'])
onMousewheel(event) {
const element = this.scrollPoint.nativeElement;
const viewportOffset = element.getBoundingClientRect();
const top = viewportOffset.top;
if (top <= 150 && this.horizon.nativeElement.scrollLeft < this.horizon1.nativeElement.offsetWidth < this.horizon2.nativeElement.offsetWidth < this.horizon3.nativeElement.offsetWidth < this.horizon4.nativeElement.offsetWidth && event.wheelDelta < 0) {
event.preventDefault();
this.horizon.nativeElement.scrollLeft += event.deltaY;
} else if (top >= 50 && this.horizon.nativeElement.scrollLeft > 0 && event.wheelDelta > 0) {
event.preventDefault();
this.horizon.nativeElement.scrollLeft += event.deltaY;
}
}
.content {
height: 100vh;
}
.home-8-sub-cont2 {
overflow-x: scroll;
white-space: nowrap;
}
.container1 {
width: 100%;
display: inline-block;
text-align: center;
}
.home-8-sub-cont2::-webkit-scrollbar {
width: 0 !important;
}
.home-8-sub-cont2 {
overflow: -moz-scrollbars-none;
}
.home-8-sub-cont2 {
-ms-overflow-style: none;
}
<ng-container style="background-color: yellow">
<div class="content" #scrollPoint>
<div #horizon class="home-8-sub-cont2">
<div class="container1" #horizon1>
<div class="title mt-50"><span>Content!</span> Content1</div>
</div>
<div class="container1" #horizon2>
<div class="title"><span>Content!</span> Content2</div>
</div>
<div class="container1" #horizon3>
<div class="title"><span>Content!</span> Content3</div>
</div>
<div class="container1" #horizon4>
<div class="title"><span>Content!</span> Content4</div>
</div>
</div>
</div>
</ng-container>

How to create right and left buttons to move product carousel in jQuery?

Investigating and, putting together my code little by little, I have achieved a carousel with the mouseup function that allows me to move the products by pressing the left button of the mouse without releasing it, so far it goes very well, well sometimes it remains as stalled, that is, without having pressed if I move the pointer moves the products.
What I want to achieve in my code is to be able to integrate two buttons, one right and one left, to also be able to move the products of the carousel in that way. How can I achieve it, can you explain to me?
var direction_slider = "up";
var current_step = 0;
var scroll_product = false;
var scroll = -1;
$(function(){
// vars for clients list carousel
var $product_carousel = $('.slider');
var products = $product_carousel.children().length;
var product_width = (products * 140); // 140px width for each client item
$product_carousel.css('width',product_width);
var rotating = true;
//var product_speed = 1800;
//var see_products = setInterval(rotateClients, product_speed);
$(document).on({
mouseenter: function(){
rotating = false; // turn off rotation when hovering
},
mouseleave: function(){
rotating = true;
}
}, '#carousel');
$product_carousel.on("mousedown", function(e) {
scroll_product = true;
scroll = e.pageX;
event.preventDefault();
}).on("mouseup", function(e) {
scroll_product = false;
var num = Math.floor(Math.abs(scroll - e.pageX) / 140);
var dir = scroll - e.pageX < 0 ? "up" : "down";
for (var x = 0; x < num; x++) {
var $first = $('.slider .item:first');
var $last = $('.slider .item:last');
if (dir == "up") {
$last.prependTo(".slider");
} else {
$first.appendTo(".slider");
}
}
$(".slider").css("transform", "translate(0, 0)")
}).on("mousemove", function(e) {
if (scroll_product) {
$(".slider").css("transform", "translate(" + ( e.pageX - scroll ) +"px, 0)")
}
});
});
.carousel {
margin: 0 auto;
padding: 1em;
width: 100%;
max-width: 1170px;
margin-left: auto;
overflow: hidden;
}
.slider {
width: 100% !important;
display: flex;
}
.item {
display: inline-table;
width: 280px;
height: 325px;
margin: 0.5em;
border: 1px solid #ccc;
}
a {
color: #8563CF;
text-decoration: none;
font-weight: 100;
}
.thumbnail {
height: 150px;
position: relative;
}
.thumbnail img {
height: 100%;
width: 100%;
object-fit: cover;
object-position: 50% 15%;
}
img {
border: 0;
height: auto;
max-width: 100%;
vertical-align: middle;
}
.p1em {
padding: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="carousel">
<div id="carousel">
<div class="slider" style="width: 280px; transform: translate(0px, 0px);">
<div class="item product">
<a href="#">
<div class="thumbnail image">
<img src="https://i.ytimg.com/vi/ZxrUVuOqsy0/maxresdefault.jpg">
</div>
<div class="box p1em">
<div class="heading ellipsis">
<h3>Prueba 1</h3>
</div>
<div class="author">
<span></span>
</div>
<div class="price right">
<p>
<label></label>
<em class="item-price">$40.130,00</em>
</p>
</div>
</div>
</a>
</div> <div class="item product">
<a href="#">
<div class="thumbnail image">
<img src="https://i.ytimg.com/vi/ZxrUVuOqsy0/maxresdefault.jpg">
</div>
<div class="box p1em">
<div class="heading ellipsis">
<h3>Curso de PHP 8 básico, intermedio y, avanzado. </h3>
</div>
<div class="author">
<span>Acaded</span>
</div>
<div class="purchased items-center">
<button>Ir al curso</button>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
The goal here is to shift the order of elements to the left or right. With jQuery this is exceptionally easy.
The logic is as so:
To shift the order to the right, select the last item, delete it, then insert before the first item
To shift the order to the left, select the first item, delete it, then insert after the last item
To achieve this, we attach a click event listener to each respective button. We select all the slider items with the selector $('.item.product'), use last() and first() to get the first and last items, and the remove() function to delete the element. Then, to reorder, we use jQuery's insertBefore() and insertAfter().
This is the result:
$('#right').click(function() {
$('.item.product').last().remove().insertBefore($('.item.product').first());
})
$('#left').click(function() {
$('.item.product').first().remove().insertAfter($('.item.product').last());
})
And the rest is just a matter of styling (note: uses Material Icons for the arrow icons). Define two button elements;
<button id="left" class="nav-btn"><i class="material-icons">chevron_left</i></button>
<button id="right" class="nav-btn"><i class="material-icons">chevron_right</i></button>
The "chevron_right" and "chevron_left" are icon names | List of Icons
Set their position to fixed so that their position isn't lost when the user scrolls. Set the top attribute to calc(50vh - 50px), where 50vh is half the height of the viewport and 50px is the height of the button (to make it exactly in the "center").
A full example (best viewed in full page mode):
var direction_slider = "up";
var current_step = 0;
var scroll_product = false;
var scroll = -1;
$(function() {
$('#right').click(function() {
$('.item.product').last().remove().insertBefore($('.item.product').first());
})
$('#left').click(function() {
$('.item.product').first().remove().insertAfter($('.item.product').last());
})
var $product_carousel = $('.slider');
var products = $product_carousel.children().length;
var product_width = (products * 140);
$product_carousel.css('width', product_width);
var rotating = true;
$(document).on({
mouseenter: function() {
rotating = false;
},
mouseleave: function() {
rotating = true;
}
}, '#carousel');
$product_carousel.on("mousedown", function(e) {
scroll_product = true;
scroll = e.pageX;
event.preventDefault();
}).on("mouseup", function(e) {
scroll_product = false;
var num = Math.floor(Math.abs(scroll - e.pageX) / 140);
var dir = scroll - e.pageX < 0 ? "up" : "down";
for (var x = 0; x < num; x++) {
var $first = $('.slider .item:first');
var $last = $('.slider .item:last');
if (dir == "up") {
$last.prependTo(".slider");
} else {
$first.appendTo(".slider");
}
}
$(".slider").css("transform", "translate(0, 0)")
}).on("mousemove", function(e) {
if (scroll_product) {
$(".slider").css("transform", "translate(" + (e.pageX - scroll) + "px, 0)")
}
});
});
/* button integration styling (start) */
#left {
left: 10px;
}
#right {
right: 10px;
}
.nav-btn {
position: fixed;
top: calc(50vh - 50px);
z-index: 100;
z-index: 100;
height: 50px;
width: 50px;
border-radius: 50%;
cursor: pointer;
background-color: white;
box-shadow: 0 0 1px black;
transition: 0.2s;
}
.nav-btn:hover {
background-color: #d1d1d1;
}
/* button integration styling (end) */
.carousel {
margin: 0 auto;
padding: 1em;
width: 100%;
max-width: 1170px;
margin-left: auto;
overflow: hidden;
}
.slider {
width: 100% !important;
display: flex;
}
.item {
display: inline-table;
width: 280px;
height: 325px;
margin: 0.5em;
border: 1px solid #ccc;
}
a {
color: #8563CF;
text-decoration: none;
font-weight: 100;
}
.thumbnail {
height: 150px;
position: relative;
}
.thumbnail img {
height: 100%;
width: 100%;
object-fit: cover;
object-position: 50% 15%;
}
img {
border: 0;
height: auto;
max-width: 100%;
vertical-align: middle;
}
.p1em {
padding: 1em;
}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="carousel">
<button id="left" class="nav-btn"><i class="material-icons">chevron_left</i></button>
<button id="right" class="nav-btn"><i class="material-icons">chevron_right</i></button>
<div id="carousel">
<div class="slider" style="width: 280px; transform: translate(0px, 0px);">
<div class="item product">
<a href="#">
<div class="thumbnail image">
<img src="https://i.ytimg.com/vi/ZxrUVuOqsy0/maxresdefault.jpg">
</div>
<div class="box p1em">
<div class="heading ellipsis">
<h3>Prueba 1</h3>
</div>
<div class="author">
<span></span>
</div>
<div class="price right">
<p>
<label></label>
<em class="item-price">$40.130,00</em>
</p>
</div>
</div>
</a>
</div>
<div class="item product">
<a href="#">
<div class="thumbnail image">
<img src="https://i.ytimg.com/vi/ZxrUVuOqsy0/maxresdefault.jpg">
</div>
<div class="box p1em">
<div class="heading ellipsis">
<h3>Curso de PHP 8 básico, intermedio y, avanzado. </h3>
</div>
<div class="author">
<span>Acaded</span>
</div>
<div class="purchased items-center">
<button>Ir al curso</button>
</div>
</div>
</a>
</div>
<div class="item product">
<a href="#">
<div class="thumbnail image">
<img src="https://www.gravatar.com/avatar/0fdacb141bca7fa57c392b5f03872176?s=96&d=identicon&r=PG&f=1">
</div>
<div class="box p1em">
<div class="heading ellipsis">
<h3>Spectric</h3>
</div>
<div class="author">
<span>Spectric</span>
</div>
<div class="purchased items-center">
<button>Check out</button>
</div>
</div>
</a>
</div>
</div>
</div>
</div>

HTML `dialog` element: scroll content independently of background

I am trying to use the dialog element.
When the dialog/modal is closed, the body should be scrollable.
When the dialog/modal is open, if it has large contents, the dialog/modal should be scrollable.
However, when the dialog/modal is open, I don't want scroll to apply to both the dialog/modal and the body background, which is what it seems to do by default.
Example: https://output.jsbin.com/mutudop/3.
How can I make scroll apply only to the dialog/modal contents, when the dialog/modal is open?
Note: I am only interested in solutions using the native dialog element.
So I tried it as well and came up with this:
(function() {
var openBtn = document.querySelector("button#open");
var myDialog = document.querySelector("dialog");
openBtn.addEventListener('click', function() {
if (typeof myDialog.showModal === "function") {
myDialog.showModal();
document.querySelector("body").classList.add("overflow-hidden");
} else {
alert("Dialog API not supported by browser");
}
});
})();
* {
box-sizing: border-box;
}
.wrapper {
height: 10000px;
}
dialog {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
border: 0;
z-index: 100;
background: transparent;
overflow-y: auto;
}
dialog>div {
width: 50%;
height: 500px;
background: white;
border: 3px solid black;
margin: 0 auto;
margin-top: 50px;
}
.overflow-hidden {
overflow: hidden;
}
<div class="wrapper">
<dialog>
<div>
<form method="dialog">
<button onclick='document.body.classList.remove("overflow-hidden");' value="cancel">Cancel</button>
</form>
</div>
</dialog>
<button id="open">Open Dialog</button>
<h4>You can scroll the body now but not when the dialog is opened.</h4>
</div>
You might have noticed that I added two lines of JS to hide/show the overflow of the body and you will probably need them as you can't target the body with pure CSS if you want to check if the dialog is opened or not.
If you don't want them you can remove them and it just works fine. However, you will have two scroll bars on the right side. This is how it looks without the JS:
(function() {
var openBtn = document.querySelector("button#open");
var myDialog = document.querySelector("dialog");
openBtn.addEventListener('click', function() {
if (typeof myDialog.showModal === "function") {
myDialog.showModal();
} else {
alert("Dialog API not supported by browser");
}
});
})();
* {
box-sizing: border-box;
}
.wrapper {
height: 10000px;
}
dialog {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
border: 0;
z-index: 100;
background: transparent;
overflow-y: auto;
}
dialog>div {
width: 50%;
height: 500px;
background: white;
border: 3px solid black;
margin: 0 auto;
margin-top: 50px;
}
.overflow-hidden {
overflow: hidden;
}
<div class="wrapper">
<dialog>
<div>
<form method="dialog">
<button value="cancel">Cancel</button>
</form>
</div>
</dialog>
<button id="open">Open Dialog</button>
</div>
If you need any explanation let me know but I believe the code should be self-explanatory.
This answer takes the escape key into account. I add a keydown event listener to document.documentElement rather than the actual dialog elements. This is because when a dialog has a keydown event listener, it doesn't always fire. For example, if a dialog is open and a button inside of it has focus and you push the escape key, the keydown event listener will fire. But let's suppose that the dialog has some text in it and you highlight the text and then push the escape key. In this scenario, the keydown event listener will not fire.
const activeModals = [];
function openModal(dialogSelector) {
const dialog = document.querySelector(dialogSelector);
dialog.showModal();
activeModals.push(dialog);
document.body.classList.add('overflow-hidden');
}
function closeActiveModal() {
const activeModal = activeModals.pop();
activeModal.close();
if (activeModals.length === 0) {
document.body.classList.remove('overflow-hidden');
}
}
document.documentElement.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && activeModals.length) {
e.preventDefault();
closeActiveModal();
}
});
document.querySelectorAll('[data-toggle="modal"]').forEach((button) => {
button.addEventListener('click', () => {
openModal(button.getAttribute('data-target'));
});
});
document.querySelectorAll('[data-dismiss="modal"]').forEach((button) => {
button.addEventListener('click', closeActiveModal);
});
let fillerHtml = '';
for (let i = 1; i <= 100; i++) {
fillerHtml += `<p>${i}</p>`;
}
document.querySelectorAll('.filler').forEach((div) => {
div.innerHTML = fillerHtml;
});
.overflow-hidden {
overflow: hidden;
}
p {
font-size: 20px;
}
<button data-toggle="modal" data-target="#dialog1">Open Dialog 1</button>
<dialog id="dialog1">
<h1>Dialog 1</h1>
<button data-dismiss="modal">Close Dialog 1</button>
<button data-toggle="modal" data-target="#dialog2">Open Dialog 2</button>
<div class="filler"></div>
</dialog>
<dialog id="dialog2">
<h1>Dialog 2</h1>
<button data-dismiss="modal">Close Dialog 2</button>
</dialog>
<div class="filler"></div>
Update
I created another example where your main content is not scrolled with your modal if it is larger than your main content. You can set position to fixed on your container to achieve this.
(function() {
var openBtn = document.getElementById('open-dialog');
var myDialog = document.getElementById('my-dialog');
openBtn.addEventListener('click', function() {
if (typeof myDialog.showModal === "function") {
myDialog.showModal();
} else {
alert("Dialog API not supported by browser");
}
});
})();
#container {
height: 100vh;
width: 100vw;
position: fixed;
top: 0;
left: 0;
background: #ccc;
}
#my-dialog {
margin-top: 1rem;
margin-bottom: 3rem;
top: 3rem;
width: 50%;
overflow-y: auto;
}
#my-dialog__content {
display: flex;
flex-direction: column;
height: 200vh;
}
menu {
width: 100%;
padding: 0;
margin: 0 auto;
}
#cancel-button {
width: 100%
}
<div id="container">
<dialog id="my-dialog">
<div id="my-dialog__content">
<form method="dialog">
<menu>
<button id="cancel-button" value="cancel">Cancel</button>
</menu>
</form>
</div>
</dialog>
<menu>
<button id="open-dialog">Open Dialog</button>
</menu>
</div>
Original answer
You can set a max-height on your dialog and style the contents of your dialog accordingly. See example below.
(function() {
var openBtn = document.getElementById('open-dialog');
var myDialog = document.getElementById('my-dialog');
openBtn.addEventListener('click', function() {
if (typeof myDialog.showModal === "function") {
myDialog.showModal();
} else {
alert("Dialog API not supported by browser");
}
});
})();
#my-dialog {
width: 50%;
max-height: 50vh;
overflow-y: auto;
}
#my-dialog__content {
display: flex;
flex-direction: column;
height: 150vh;
}
menu {
width: 100%;
padding: 0;
margin: 0 auto;
}
#cancel-button {
width: 100%
}
<div id="container">
<dialog id="my-dialog">
<div id="my-dialog__content">
<form method="dialog">
<menu>
<button id="cancel-button" value="cancel">Cancel</button>
</menu>
</form>
</div>
</dialog>
<menu>
<button id="open-dialog">Open Dialog</button>
</menu>
</div>
Simple solution is : Once the mnodel is displayed make a one more DIV as overlay which covers full screen, in that place css { pointer-events:none} and model will be placed on top of that. user can not click on body content other than model data.
I have created sample: http://jsfiddle.net/z3sgvnox/
<body id="content-body">
<div id="container">
<dialog id="my-dialog">
<div id="my-dialog__content">
<form method="dialog">
<menu>
<button id="cancel-button" value="cancel">Cancel</button>
</menu>
</form>
</div>
</dialog>
<menu>
<button id="open-dialog">Open Dialog</button>
</menu>
</div>
</body>
CSS
#container {
height: 100vh;
width: 100vw;
position: fixed;
top: 0;
left: 0;
background: #ccc;
}
#my-dialog {
margin-top: 1rem;
margin-bottom: 3rem;
width: 50%;
overflow-y: auto;
max-height: 80%;
}
.hideScroll{
overflow:hidden;
pointer-events:none;
}
#my-dialog__content {
display: flex;
flex-direction: column;
height: 200vh;
}
menu {
width: 100%;
padding: 0;
margin: 0 auto;
}
#cancel-button {
width: 100%
}
JS:
(function() {
var openBtn = document.getElementById('open-dialog');
var myDialog = document.getElementById('my-dialog');
var bodyData = document.getElementById('content-body');
openBtn.addEventListener('click', function() {
if (typeof myDialog.showModal === "function") {
myDialog.showModal();
bodyData.classList.add("hideScroll");
} else {
alert("Dialog API not supported by browser");
}
});
})();

Show/Hide Multiple Divs Javascript

Looking for a good JavaScript to help me hide/show multiple divs with a button click not an a href click so I can use it in blogger.
I've been looking for an answer for a while now and have been unable to find a good one that uses JavaScript and/or CSS. I am a bit of a novice so bear with me.
Following is my code that works but I would like to simplify it and make it work so that it will close the div when I click the appropriate button again.
css
<head>
<style>
#myDIV1 {
width: 150px;
height: 150px;
background-color: lightblue;
display: none;
}
#myDIV2 {
width: 150px;
height: 150px;
background-color: lightblue;
display: none;
}
#myDIV3 {
width: 150px;
height: 150px;
background-color: lightblue;
display: none;
}
#myDIV4 {
width: 150px;
height: 150px;
background-color: lightblue;
display: none;
}
</style>
</head>
I know there is an easier way but this is the only way that I can find that works for what I want it to do for the most part
html
<body>
<p>Click button to see div.</p>
<button onclick="myFunction1()">One</button>
<button onclick="myFunction2()">Two</button>
<button onclick="myFunction3()">Three</button>
<button onclick="myFunction4()">Four</button>
<div id="myDIV1">
This is the div1 element.
</div>
<div id="myDIV2">
This is the div2 element.
</div>
<div id="myDIV3">
This is the div3 element.
</div>
<div id="myDIV4">
This is the div4 element.
</div>
Javascript
<script>
function myFunction1() {
document.getElementById("myDIV1").style.display = "block";
document.getElementById("myDIV2").style.display = "none";
document.getElementById("myDIV3").style.display = "none";
document.getElementById("myDIV4").style.display = "none";
}
function myFunction2() {
document.getElementById("myDIV1").style.display = "none";
document.getElementById("myDIV2").style.display = "block";
document.getElementById("myDIV3").style.display = "none";
document.getElementById("myDIV4").style.display = "none";
}
function myFunction3() {
document.getElementById("myDIV1").style.display = "none";
document.getElementById("myDIV2").style.display = "none";
document.getElementById("myDIV3").style.display = "block";
document.getElementById("myDIV4").style.display = "none";
}
function myFunction4() {
document.getElementById("myDIV1").style.display = "none";
document.getElementById("myDIV2").style.display = "none";
document.getElementById("myDIV3").style.display = "none";
document.getElementById("myDIV4").style.display = "block";
}
</script>
Any help would be appreciated thanks in advance.
I would suggest to separate your code first - it would be then more clean and reusable - like myStyle.css, myScript.js, index.html
Add the css and js file in the html file like -
<link rel="stylesheet" type="text/css" href="myStyle.css">
<script type="text/javascript" src="myScript.js"></script>
src -> indicates the source path of the file. Here I assume that all our css, js, 'html' file in same place.
var divs = ["Div1", "Div2", "Div3", "Div4"];
var visibleDivId = null;
function divVisibility(divId) {
if(visibleDivId === divId) {
visibleDivId = null;
} else {
visibleDivId = divId;
}
hideNonVisibleDivs();
}
function hideNonVisibleDivs() {
var i, divId, div;
for(i = 0; i < divs.length; i++) {
divId = divs[i];
div = document.getElementById(divId);
if(visibleDivId === divId) {
div.style.display = "block";
} else {
div.style.display = "none";
}
}
}
.buttons a {
font-size: 16px;
}
.buttons a:hover {
cursor:pointer;
font-size: 16px;
}
<div class="main_div">
<div class="buttons">
Div1 |
Div2 |
Div3 |
Div4
</div>
<div class="inner_div">
<div id="Div1">I'm Div One</div>
<div id="Div2" style="display: none;">I'm Div Two</div>
<div id="Div3" style="display: none;">I'm Div Three</div>
<div id="Div4" style="display: none;">I'm Div Four</div>
</div>
</div>
if you want to hide/show all divs simultaneously than you have to give all divs same class for ex: .toggle and than you can do this:
function myFunction1(){
$(".toggle").slideToggle();
}
if you want to hide/show one div at a time than you can do this with id :
function myFunction1(){
$("#myDIV1").slideToggle();
}
with different buttons :
function myFunction1(id){
$("#"+id).slideToggle();
}
pass id here :
<button onclick="myFunction1('myDIV1')">One</button>
<button onclick="myFunction1('myDIV2')">Two</button>
<button onclick="myFunction1('myDIV3')">Three</button>
<button onclick="myFunction1('myDIV4')">Four</button>
I found the answer to what I wanted with the .toggle function thanks for the help. The answer I found here: radomsnippets.com
We can easily add an unlimited amount of buttons using reusable code.
here is a full example! Enjoy
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.generalclass {
width: 100%;
color: #ffffff;
text-align: center;
background-color: #000000;
margin: 10px;
padding: 10px;
display: none;
}
.button{
background: red;
padding: 10px;
border-radius: 5px;
color: #FFFFFF;
font-size: 16px;
border: none;
}
.button:hover{
background: black;
}
</style>
</head>
<body>
<button class="button" onclick="myFunction('button1')">Button 1</button>
<button class="button" onclick="myFunction('button2')">Button 2</button>
<div id="button1" class="generalclass">
<p>I can show anything here</p>
</div>
<div id="button2" class="generalclass">
<p>I can show anything here too and different from button 1</p>
</div>
<script>
function myFunction(divid) {
var x = document.getElementById(divid);
if (x.style.display == "none")
{
x.style.display = "block";
}
else {
x.style.display = "none";
}
}
</script>
</body>
</html>