//Overlay mobile menu open
$('#burger-icon').on('click', function(e) {
e.stopPropagation();
document.getElementById('fp-menu').style.height = "100%";
let overlay_content = document.getElementsByClassName("overlay-content")[0];
let pipe = overlay_content.querySelector(".pipe");
let contact = document.querySelector("#sidebar-leftButton");
let case_studies = document.querySelector("#sidebar-rightButton");
if (screen.width < 1000) {
let overlay_contentA = document.querySelectorAll(".overlay a");
for (i = 0; i < overlay_contentA.length; i++) {
overlay_contentA[i].style.color = "white";
}
//changes the social icons to white if in mobile view.
document.getElementById('instagram').src = "instagram_white.svg";
document.getElementById('linkedin').src = "linkedin_white.svg";
document.getElementById('twitter').src = "twitter_white.svg";
//gets rid of the pipe in menu that is visible for the desktop version
//removes sidetabs while in overlay menu
pipe.style.display = "none";
contact.style.display = "none";
case_studies.style.display = "none";
//changes how the elements are displayed when overlay is triggered
$('#fp-menu .news').removeClass("col-sm-2");
$('#fp-menu .portfolio').removeClass("col-sm-3");
$('#fp-menu #social').removeClass("col-sm-6");
}
});
function closeOverlayMenu() { //closes the overlay mobile menu
// e.stopPropagation();
$('#fp-menu').animateCss('slideUp');
$('#fp-menu').css('height', 0);
let overlay_content = document.getElementsByClassName("overlay-content")[0];
let pipe = overlay_content.querySelector(".pipe");
let contact = document.querySelector("#sidebar-leftButton");
let case_studies = document.querySelector("#sidebar-rightButton");
let overlay_contentA = document.querySelectorAll(".overlay a");
for (i = 0; i < overlay_contentA.length; i++) {
overlay_contentA[i].style.color = "black";
}
//changes icons to black on slide up of overlay
document.getElementById('instagram').src = "instagram.svg";
document.getElementById('linkedin').src = "linkedin.svg";
document.getElementById('twitter').src = "twitter.svg";
//restores elements of the original homepage that were hidden for overlay
pipe.style.display = "block";
contact.style.display = "block";
case_studies.style.display = "block";
$('#fp-menu .news').addClass("col-sm-2");
$('#fp-menu .portfolio').addClass("col-sm-3");
$('#fp-menu #social').addClass("col-sm-6");
};
document.getElementsByTagName('body')[0].onresize = function() {
closeOverlayMenu();
};
//overlay mobile menu close
$('#closebtn').on('click', function(e) {
e.stopPropagation();
$('#fp-menu').animateCss('slideUp');
$('#fp-menu').css('height', 0);
//if overlay mobile menu is down, close it by clicking the X
if (screen.width < 1000) {
closeOverlayMenu();
console.log(document.querySelectorAll("#social"));
}
});
//overlay menu styling
.overlay {
height: 0;
width: 100%;
position: fixed;
z-index: 999;
top: 0;
left: 0;
background-color: #000000;
overflow-x: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 5%;
width: 100%;
text-align: center !important;
margin-top: 90px;
.row{
padding: 50px 30px 50px 30px;
.column{
float: left;
width: 33.33%;
padding: 0 5px 0 5px;
}
}
img {
width: 50px;
}
div {
padding: 30px 0 30px 0;
}
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #FFFFFF;
}
.overlay a:hover, .overlay a:focus {
color: #f1f1f1;
}
#closebtn {
display:block;
position: relative;
top: 5px;
right: 20px;
font-size: 60px;
}
#social{
position: relative;
top: 10px;
a {
padding: 5% 5% 5% 5%;
}
}
#fp-menu{
display: block;
color: $menu_black;
}
.pipe{
display: block;
transition: 0.4s;
}
<div id="fp-menu" class="overlay">
<div id="closebtn" style="color: white;">X</div>
<div class="column overlay-content">
<!-- <div class="column"> -->
<div class="col-sm-2 news">
NEWS
</div>
<div class="col-sm-1 pipe">
|
</div>
<div class="col-sm-3 portfolio">
PORTFOLIO
</div>
<div id="social" class="col-sm-6">
<img id="instagram" src='instagram.svg' />
<img id="linkedin" src='linkedin.svg' />
<img id="twitter" src='twitter.svg' />
</div>
</div>
</div>
So the weirdest thing, I've got 1 function that is to trigger under 2 conditions: when the window is resized and when the exit button is clicked.
This relates to an overlay menu that's actually intended for mobile users.
The functions work as they are supposed to, in both cases, when I have the inspection console open in chrome. However, when I close this and return to the normal browser window, the functions cease to execute.
On the mobile it is fine. I have only encountered this problem on the desktop/laptop (as I tried it on different desktops [iMacs] and 2 laptops [Macbooks, but the type of hardware I don't think matters]).
Currently the icons in the "#social" div are not being changed to white, which is what I expect to happen when opened, and when closed, they return to black. They are staying black throughout the execution.
Has anyone ever experienced this before? This is related to a Wordpress platform site. Totally custom built, no themes.
Please let me know if this description helps. If any code is needed, please let me know.
Ps: I thought it was a caching problem, on the terminals or on the server, and I cleared the cache on both but the issue still persists.
function closeOverlayMenu(){//closes the overlay mobile menu
$('#fp-menu').animateCss('slideUp');
$('#fp-menu').css('height', 0);
let overlay_content = document.getElementsByClassName("overlay-content")[0];
let pipe = overlay_content.querySelector(".pipe");
let contact = document.querySelector("#sidebar-leftButton");
let case_studies = document.querySelector("#sidebar-rightButton");
let overlay_contentA = document.querySelectorAll(".overlay a");
for (i = 0; i < overlay_contentA.length; i++) {
overlay_contentA[i].style.color = "black";
}
//changes icons to black on slide up of overlay
document.getElementById('instagram').src="https://s3-eu-west-1.amazonaws.com/mvt-hosted-images/instagram.svg";
document.getElementById('linkedin').src="https://s3-eu-west-1.amazonaws.com/mvt-hosted-images/linkedin.svg";
document.getElementById('twitter').src="https://s3-eu-west-1.amazonaws.com/mvt-hosted-images/twitter.svg";
//restores elements of the original homepage that were hidden for overlay
pipe.style.display="block";
contact.style.display="block";
case_studies.style.display="block";
$('#fp-menu .news').addClass("col-sm-2");
$('#fp-menu .portfolio').addClass("col-sm-3");
$('#fp-menu #social').addClass("col-sm-6");
};
I would expect that the function would trigger without the dev console being active. Please let me know if any further description or information would help.
Related
I have this simple collapsible menu on www.keokuk.com
I would like for the previous menu to close when you click on the next one.
this is the javascript:
<script>
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function () {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
</script>
I worked on a solution on your website.
But it appears you set max-height manually in an other javascript function so you can just do the same thing in the commented line.
document.querySelectorAll('.collapsible').forEach(el => {
el.addEventListener('click', (e) => {
document.querySelectorAll('.collapsible').forEach(e => {
e.classList.remove('active');
e.nextSibling.nextElementSibling.style.maxHeight = "0px";
});
e.target.classList.toggle('active');
e.target.nextSibling.nextElementSibling.style.maxHeight =
`${el.nextSibling.nextElementSibling.scrollHeight}px`;
});
});
Details are commented in example
// Collect all .switch into an array
const switches = [...document.querySelectorAll(".switch")];
// Bind each .switch to the click event
switches.forEach(s => s.addEventListener("click", openClose));
// Event handler passes Event Object as default
function openClose(event) {
// Reference the tag proceeding clicked tag
const content = this.nextElementSibling;
// Get the height of content
let maxHt = content.scrollHeight + 'px';
// Find the index position of clicked tag
let index = switches.indexOf(this);
// The clicked tag will toggle .active class
this.classList.toggle('active');
// Remove .active class from all .switch
switches.forEach((btn, idx) => {
/*
If current index does NOT equal index of
clicked tag...
...remove .active
*/
if (idx != index) {
btn.classList.remove('active');
}
});
/*
If clicked has .active class...
...set style property of max-height using CSS variables
*/
if (this.classList.contains('active')) {
content.style.setProperty('--maxH', maxHt + 'px');
} else {
content.style.setProperty('--maxH', '0px');
}
}
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box
}
:root {
font: 300 1.5ch/1.2 'Segoe UI';
--maxH: 0px;
}
body {
width: 100%;
min-height: 200%;
padding: 15px;
}
header {
width: max-content;
margin: 10px 0 0;
padding: 5px 10px;
border: 3px ridge black;
border-radius: 4px;
background: #aaa;
cursor: pointer;
}
section {
position: relative;
max-height: var(--maxH);
margin: 0;
padding: 5px 10px;
border: 3px ridge black;
border-radius: 4px;
background: #ddd;
opacity: 0;
pointer-events: none;
}
.active+section {
z-index: 1;
opacity: 1.0;
}
<header class='switch'>Read more...</header>
<section>
<p>Merchandise Morty, your only purpose in life is to buy & consume merchandise and you did it, you went into a store an actual honest to god store and you bought something, you didn't ask questions or raise ethical complaints you just looked into
the bleeding jaws of capitalism and said 'yes daddy please' and I'm so proud of you, I only wish you could have bought more, I love buying things so much Morty. Morty, you know outer space is up right? Are you kidding? I'm hoping I can get to both
of them, Rick! And there's no evidence that a Latino student did it.</p>
</section>
<header class='switch'>Read more...</header>
<section>
<p>Oh, I'm sorry Morty, are you the scientist or are you the kid who wanted to get laid? Why don't you ask the smartest people in the universe, Jerry? Oh yeah you can't. They blew up. Looossseeerrrrr. I am not putting my father in a home! He just came
back into my life, and you want to, grab him and, stuff him under a mattress like last month's Victoria's Secret?!
</p>
</section>
I am trying to create a vertical slide show on scroll. One picture-screen glide over the next one, and then the second over the third, and so on…
HTML/CSS structure looks as following: external container has display property relative. Inside it there are several containers with images with the property fixed, so that they are all as a card deck and you pull card by card from the top.
JavaScript function should load the first pare of image-pages and follow the amount of scrolled distance changing the index of the image-page and changing the z-index of the layer (the top one: 2, the one blow: 1 and so on...)
var mansDok = []; var paklajAttal = [];
// Find all the slides containers
mansDok = document.getElementsByClassName("slaide");
// Find all the slides IDs
for(i=0; i<mansDok.length; i++) {
paklajAttal[i] = mansDok[i].id;
}
// Height of the browser window
var logAugst = document.documentElement.clientHeight;
// Start function on scrolling the contents
window.onscroll = function() {vertikSlaidrade()};
//
// Slideshow function
function vertikSlaidrade() {
var k = 0; var i = 0, winScroll;
// How far the screen been scrolled
winScroll = document.documentElement.scrollTop || document.body.scrollTop;
// Change slides while scrolling
if(winScroll <= logAugst * 1) {
document.getElementById(paklajAttal[k]).style.zIndex = "2";
document.getElementById(paklajAttal[k]).style.position = "relative";
document.getElementById(paklajAttal[k+1]).style.display = "block";
document.getElementById(paklajAttal[k+1]).style.position = "fixed";
} else if(winScroll <= logAugst * 2) {
document.getElementById(paklajAttal[k+1]).style.zIndex = "3";
document.getElementById(paklajAttal[k+1]).style.position = "relative";
document.getElementById(paklajAttal[k+2]).style.display = "block";
document.getElementById(paklajAttal[k+2]).style.position = "fixed";
} else if(winScroll <= logAugst * 2.8) {
document.getElementById(paklajAttal[k+2]).style.zIndex = "4";
document.getElementById(paklajAttal[k+2]).style.position = "relative";
document.getElementById(paklajAttal[k+3]).style.display = "block";
document.getElementById(paklajAttal[k+3]).style.position = "fixed";
} else if(winScroll > logAugst * 2.8) {
// Run reset function by the end of slides
atiestat();
}
}
// Function to reset the slides properties
function atiestat() {
for(var i=0; i<mansDok.length; i++) {
document.getElementById(paklajAttal[i]).style.zIndex = "0";
document.getElementById(paklajAttal[i]).style.position = "absolute";
document.getElementById(paklajAttal[i]).style.display = "none";
}
// Show the first pair of slides
document.getElementById(paklajAttal[0]).style.display = "block";
document.getElementById(paklajAttal[0]).style.zIndex = "2";
document.getElementById(paklajAttal[1]).style.position = "fixed";
document.getElementById(paklajAttal[1]).style.zIndex = "1";
}
* {box-sizing: border-box;}
html, body{
height: 100%;
margin: 0px;
padding: 0px;
background-color: #000;
font-size: 1em;
}
main {
position: relative;
margin: 0px;
padding: 0px;
width: 100%;
overflow-x: hidden;
overflow-y: auto;
}
/* Page with slide */
.slaide {
position: absolute;
top: 0px;
left: 0px;
z-index: 0;
margin: 0px;
padding: 0px;
width: 100%;
display: none;
}
.slaide img {
width: 1230px; /* Doesn't work below this value !?!? */
}
/* Empty filler */
.tukss {
display: block;
margin: 0px;
padding: 0px;
height: 1000px; /* Do NOT reduce this value!!! */
}
<main>
<div class="slaide" id="lapa1" style="display: block;">
<img src="https://www.w3schools.com/howto/img_parallax.jpg">
</div>
<div class="slaide" id="lapa2">
<img src="https://www.w3schools.com/howto/img_parallax2.jpg">
</div>
<div class="slaide" id="lapa3">
<img src="https://www.w3schools.com/howto/img_parallax3.jpg">
</div>
<div class="tukss" id="tukss"></div>
</main>
May be its not the most elegant version of JS code, but everything works perfectly as I wanted. Somehow it doesn’t work if I change the image size below 1230px or to 100% and reduce the width of the browser window. (Images are from W3Schools.com)
I would appreciate if somebody could help me out with this situation.
I have 2 boxes and a vertical div line in one unique container div (code and fiddle below).
I'm using CSS grids to position my elements inside the container
What I'd like to accomplish is to use the vertical line to resize horizontally the two boxes based on the position of the vertical line.
I apologize if the question is noobish, I am new to web development, only used Python before, already tried to google and stackoverflow search but all solutions seem overly complicated and generally require additional libraries, I was looking for something simpler and JS only.
HTML:
<div class="wrapper">
<div class="box a">A</div>
<div class="handler"></div>
<div class="box b">B</div>
</div>
CSS:
body {
margin: 40px;
}
.wrapper {
display: grid;
grid-template-columns: 200px 8px 200px;
grid-gap: 10px;
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
resize: both;
}
.handler{
width: 3px;
height: 100%;
padding: 0px 0;
top: 0;
background: red;
draggable: true;
}
https://jsfiddle.net/gv8Lwckh/6/
What you intend to do can be done using CSS flexbox—there is no need to use CSS grid. The bad news is that HTML + CSS is not so smart that declaring resize and draggable will make the layout flexible and adjustable by user interaction. For that, you will have to use JS. The good news is that this is actually not too complicated.
Here is a quick screen grab of output the code below:
However, for you to understand the code I will post below, you will have to familiarize yourself with:
Event binding using .addEventListener. In this case, we will use a combination of mousedown, mouseup and mousemove to determine whether the user is in the middle of dragging the element
CSS flexbox layout
Description of the solution
Initial layout using CSS
Firstly, you will want to layout your boxes using CSS flexbox. We simply declare display: flex on the parent, and then use flex: 1 1 auto (which translates to "let the element grow, let the element shrink, and have equal widths). This layout is only valid at the initial rendering of the page:
.wrapper {
/* Use flexbox */
display: flex;
}
.box {
/* Use box-sizing so that element's outerwidth will match width property */
box-sizing: border-box;
/* Allow box to grow and shrink, and ensure they are all equally sized */
flex: 1 1 auto;
}
Listen to drag interaction
You want to listen to mouse events that might have originated from your .handler element, and you want a global flag that remembers whether the user is dragging or not:
var handler = document.querySelector('.handler');
var isHandlerDragging = false;
Then you can use the following logic to check if the user is dragging or not:
document.addEventListener('mousedown', function(e) {
// If mousedown event is fired from .handler, toggle flag to true
if (e.target === handler) {
isHandlerDragging = true;
}
});
document.addEventListener('mousemove', function(e) {
// Don't do anything if dragging flag is false
if (!isHandlerDragging) {
return false;
}
// Set boxA width properly
// [...more logic here...]
});
document.addEventListener('mouseup', function(e) {
// Turn off dragging flag when user mouse is up
isHandlerDragging = false;
});
Computing the width of box A
All you are left with now is to compute the width of box A (to be inserted in the [...more logic here...] placeholder in the code above), so that it matches that of the movement of the mouse. Flexbox will ensure that box B will fill up the remaining space:
// Get offset
var containerOffsetLeft = wrapper.offsetLeft;
// Get x-coordinate of pointer relative to container
var pointerRelativeXpos = e.clientX - containerOffsetLeft;
// Resize box A
// * 8px is the left/right spacing between .handler and its inner pseudo-element
// * Set flex-grow to 0 to prevent it from growing
boxA.style.width = (pointerRelativeXpos - 8) + 'px';
boxA.style.flexGrow = 0;
Working example
var handler = document.querySelector('.handler');
var wrapper = handler.closest('.wrapper');
var boxA = wrapper.querySelector('.box');
var isHandlerDragging = false;
document.addEventListener('mousedown', function(e) {
// If mousedown event is fired from .handler, toggle flag to true
if (e.target === handler) {
isHandlerDragging = true;
}
});
document.addEventListener('mousemove', function(e) {
// Don't do anything if dragging flag is false
if (!isHandlerDragging) {
return false;
}
// Get offset
var containerOffsetLeft = wrapper.offsetLeft;
// Get x-coordinate of pointer relative to container
var pointerRelativeXpos = e.clientX - containerOffsetLeft;
// Arbitrary minimum width set on box A, otherwise its inner content will collapse to width of 0
var boxAminWidth = 60;
// Resize box A
// * 8px is the left/right spacing between .handler and its inner pseudo-element
// * Set flex-grow to 0 to prevent it from growing
boxA.style.width = (Math.max(boxAminWidth, pointerRelativeXpos - 8)) + 'px';
boxA.style.flexGrow = 0;
});
document.addEventListener('mouseup', function(e) {
// Turn off dragging flag when user mouse is up
isHandlerDragging = false;
});
body {
margin: 40px;
}
.wrapper {
background-color: #fff;
color: #444;
/* Use flexbox */
display: flex;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
/* Use box-sizing so that element's outerwidth will match width property */
box-sizing: border-box;
/* Allow box to grow and shrink, and ensure they are all equally sized */
flex: 1 1 auto;
}
.handler {
width: 20px;
padding: 0;
cursor: ew-resize;
flex: 0 0 auto;
}
.handler::before {
content: '';
display: block;
width: 4px;
height: 100%;
background: red;
margin: 0 auto;
}
<div class="wrapper">
<div class="box">A</div>
<div class="handler"></div>
<div class="box">B</div>
</div>
Here's an example of the drag event handling, but using CSS Grids
The trick is to set the grid-template-columns (or rows) on the grid container rather than than the size of the grid items
let isLeftDragging = false;
let isRightDragging = false;
function ResetColumnSizes() {
// when page resizes return to default col sizes
let page = document.getElementById("pageFrame");
page.style.gridTemplateColumns = "2fr 6px 6fr 6px 2fr";
}
function SetCursor(cursor) {
let page = document.getElementById("page");
page.style.cursor = cursor;
}
function StartLeftDrag() {
// console.log("mouse down");
isLeftDragging = true;
SetCursor("ew-resize");
}
function StartRightDrag() {
// console.log("mouse down");
isRightDragging = true;
SetCursor("ew-resize");
}
function EndDrag() {
// console.log("mouse up");
isLeftDragging = false;
isRightDragging = false;
SetCursor("auto");
}
function OnDrag(event) {
if (isLeftDragging || isRightDragging) {
// console.log("Dragging");
//console.log(event);
let page = document.getElementById("page");
let leftcol = document.getElementById("leftcol");
let rightcol = document.getElementById("rightcol");
let leftColWidth = isLeftDragging ? event.clientX : leftcol.clientWidth;
let rightColWidth = isRightDragging ? page.clientWidth - event.clientX : rightcol.clientWidth;
let dragbarWidth = 6;
let cols = [
leftColWidth,
dragbarWidth,
page.clientWidth - (2 * dragbarWidth) - leftColWidth - rightColWidth,
dragbarWidth,
rightColWidth
];
let newColDefn = cols.map(c => c.toString() + "px").join(" ");
// console.log(newColDefn);
page.style.gridTemplateColumns = newColDefn;
event.preventDefault()
}
}
#page {
height: 100%;
background-color: pink;
display: grid;
grid-template-areas: 'header header header header header' 'leftcol leftdragbar tabs tabs tabs' 'leftcol leftdragbar tabpages rightdragbar rightcol' 'leftcol leftdragbar footer footer footer';
grid-template-rows: min-content 1fr 9fr 1fr;
grid-template-columns: 2fr 6px 6fr 6px 2fr;
}
/*****************************/
#header {
background-color: lightblue;
overflow: auto;
grid-area: header;
}
#leftcol {
background-color: #aaaaaa;
overflow: auto;
grid-area: leftcol;
}
#leftdragbar {
background-color: black;
grid-area: leftdragbar;
cursor: ew-resize;
}
#tabs {
background-color: #cccccc;
overflow: auto;
grid-area: tabs;
}
#tabpages {
background-color: #888888;
overflow: auto;
grid-area: tabpages;
}
#rightdragbar {
background-color: black;
grid-area: rightdragbar;
cursor: ew-resize;
}
#rightcol {
background-color: #aaaaaa;
overflow: auto;
grid-area: rightcol;
}
#footer {
background-color: lightblue;
overflow: auto;
grid-area: footer;
}
<body onresize="ResetColumnSizes()">
<div id="page" onmouseup="EndDrag()" onmousemove="OnDrag(event)">
<div id="header">
Header
</div>
<div id="leftcol">
Left Col
</div>
<div id="leftdragbar" onmousedown="StartLeftDrag()"></div>
<div id="tabs">
Tabs
</div>
<div id="tabpages">
Tab Pages
</div>
<div id="rightdragbar" onmousedown="StartRightDrag()"></div>
<div id="rightcol">
Rightcol
</div>
<div id="footer">
Footer
</div>
</div>
</body>
https://codepen.io/lukerazor/pen/GVBMZK
I changed, so you can add more Horizontal and Vertical slider.
test1.html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="test1.css">
<script src= "test1.js" > </script>
</head>
<body>
<div id="page" onmouseup="EndDrag()" onmousemove="OnDrag(event)">
<div id="header">
Header asdlkj flkdfj sdflkksdjf sd;flsdjf sd;flkjsd;fljsd;flsdj;fjsd f;sdlfj;sdlfj
</div>
<div id="leftcol">
Left Col
</div>
<div id="leftdragbar" onmousedown="StartHDrag(1)"></div>
<div id="tabs">
Tabs
</div>
<div id="topdragbar" onmousedown="StartVDrag(2)"></div>
<div id="tabpages">
Tab Pages
</div>
<div id="rightdragbar" onmousedown="StartHDrag(3)"></div>
<div id="rightcol">
Rightcol
</div>
<div id="botdragbar" onmousedown="StartVDrag(4)"></div>
<div id="footer">
Footer
</div>
</div>
<div id= 'status'></div>
</body>
</html>
test1.css
body {
}
#page {
height: 100vh;
background-color: pink;
display: grid;
grid-template-areas:
'header header header header header'
'leftcol leftdragbar tabs tabs tabs'
'leftcol leftdragbar topdragbar topdragbar topdragbar'
'leftcol leftdragbar tabpages rightdragbar rightcol'
'botdragbar botdragbar botdragbar botdragbar botdragbar'
'footer footer footer footer footer';
grid-template-rows: min-content 1fr 6px 9fr 6px 1fr;
grid-template-columns: 2fr 6px 6fr 6px 2fr;
}
/*****************************/
#header {
background-color: lightblue;
overflow: auto;
grid-area: header;
}
#leftcol {
background-color: #aaaaaa;
overflow: auto;
grid-area: leftcol;
}
#leftdragbar {
background-color: black;
grid-area: leftdragbar;
cursor: ew-resize;
}
#topdragbar {
background-color: black;
grid-area: topdragbar;
cursor: ns-resize;
}
#botdragbar {
background-color: black;
grid-area: botdragbar;
cursor: ns-resize;
}
#tabs {
background-color: #cccccc;
overflow: auto;
grid-area: tabs;
}
#tabpages {
background-color: #888888;
overflow: auto;
grid-area: tabpages;
}
#rightdragbar {
background-color: black;
grid-area: rightdragbar;
cursor: ew-resize;
}
#rightcol {
background-color: #aaaaaa;
overflow: auto;
grid-area: rightcol;
}
#footer {
background-color: lightblue;
overflow: auto;
grid-area: footer;
}
test1.js
let isHDragging = false;
let isVDragging = false;
let cols = ['2fr','6px','6fr','6px','2fr']; //grid-template-columns: 2fr 6px 6fr 6px 2fr;
let colns = ['leftcol','','tabpages','','rightcol'];
let Tcols = [];
let rows = ['min-content','1fr','6px','9fr','6px','1fr']; //grid-template-rows: min-content 1fr 6px 9fr 1fr
let rowns = ['header','tabs','','tabpages','','footer'];
let Trows = []
let CLfactor ;
let CRfactor ;
let gWcol = -1;
let gWrow = -1;
function StartHDrag(pWcol) {
isHDragging = true;
SetCursor("ew-resize");
CLfactor = parseFloat(cols[pWcol-1]) / document.getElementById(colns[pWcol-1]).clientWidth;
CRfactor = parseFloat(cols[pWcol+1]) / document.getElementById(colns[pWcol+1]).clientWidth;
Tcols = cols.map(parseFloat);
gWcol = pWcol;
}
function StartVDrag(pRow) {
isVDragging = true;
SetCursor("ns-resize");
CLfactor = parseFloat(rows[pRow-1]) / document.getElementById(rowns[pRow-1]).clientHeight;
CRfactor = parseFloat(rows[pRow+1]) / document.getElementById(rowns[pRow+1]).clientHeight;
Trows = rows.map(parseFloat);
gWrow = pRow;
}
function SetCursor(cursor) {
let page = document.getElementById("page");
page.style.cursor = cursor;
}
function EndDrag() {
isHDragging = false;
isVDragging = false;
SetCursor("auto");
}
function OnDrag(event) {
if(isHDragging) {
Tcols[gWcol-1] += (CLfactor * event.movementX);
Tcols[gWcol+1] -= (CLfactor * event.movementX);
cols[gWcol-1] = Math.max(Tcols[gWcol-1],0.01) + "fr";
cols[gWcol+1] = Math.max(Tcols[gWcol+1],0.01) + "fr";
let newColDefn = cols.join(" ");
page.style.gridTemplateColumns = newColDefn;
} else if (isVDragging) {
Trows[gWrow-1] += (CLfactor * event.movementY);
Trows[gWrow+1] -= (CLfactor * event.movementY);
rows[gWrow-1] = Math.max(Trows[gWrow-1],0.01) + "fr";
rows[gWrow+1] = Math.max(Trows[gWrow+1],0.01) + "fr";
let newRowDefn = rows.join(" ");
page.style.gridTemplateRows = newRowDefn;
document.getElementById("footer").innerHTML = newRowDefn;
}
event.preventDefault()
}
To actually match the question! Making a dragbar to resize divs inside CSS grids.
Here is a possible way, the original OP layout is kept, as well as the CSS, using Grids.
The goal is to capture the original state of the Grid Template Columns, and convert it to floats.
The browser always compute in pixels, and the sum of those columns + the gap, represent the total width of the container element. That sum must always be the same, or the elements will jump!
NB: Calls to .getComputedStyle() are not very efficient, optimisation is likely possible here!
Notice, doing this way using grids and screenX avoid the common jumping bug on mouse down.
Comments are added, this will allow to apply the logic with any number of columns, or rows, good luck.
With the usage of pointer events, it does works from a touch device as well.
let target = document.querySelector("div") // Target container element
let md = false; // Will be true at mouse down
let xorigin; // Click origin X position
let gtcorigin = []; // Origin Grid Template Columns in pixels
const pointerdown = (e) => {
if (e.target.classList[0] === "handler"){ // Filter to target the wanted element
md = true; // Set mouse down
xorigin = e.screenX; // Store the origin X position
// Grid Template Columns, array of pixels as float
gtcorigin = window.getComputedStyle(target)["grid-template-columns"].split(" ").map((a) => +(a.slice(0, -2)));
document.body.style.cursor = "col-resize" // This makes things nice
document.body.style.userSelect = "none" // This makes things nice
}
}
const pointerup = (e) => {
md = false; // Reset bool at mouse up
document.body.style.cursor = "pointer"
document.body.style.userSelect = "unset"
}
const resizer = (e) => {
if (md){ // Mouse is down hover the handler element
let gtc = window.getComputedStyle(target)["grid-template-columns"].split(" ").map((a) => +(a.slice(0, -2))); // Grid Template Columns, array of pixels as float
let xdragdif = xorigin - e.screenX; // Move in pixels since the click
gtc[0] = gtcorigin[0] - xdragdif // First column, if negative, it will grow
gtc[2] = gtcorigin[2] + xdragdif // Third column
gtc = gtc.map((a) => a+"px") // Set back the values in string with "px"
document.querySelector("console").textContent = gtc.join(" ") // !!! This is only for the demo
target.style.gridTemplateColumns = gtc.join(" ") // Apply the new Grid Template Column as inline style.
}
}
// Attach all events on the largest container element. Here the body is used.
document.body.addEventListener("pointerdown", pointerdown, false)
document.body.addEventListener("pointerup", pointerup, false)
document.body.addEventListener("pointermove", resizer, false)
body {
margin: 40px;
overflow-x: hidden
}
.wrapper {
display: grid;
grid-template-columns: 200px 8px 200px;
grid-gap: 10px;
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
.handler{
width: 3px;
height: 100%;
padding: 0px 0;
top: 0;
background: red;
cursor: col-resize
}
<div class="wrapper">
<div class="box">A</div>
<div class="handler"></div>
<div class="box">B</div>
</div>
<console></console>
No limits are applied here, this can be enhanced with CSS only, using min-width and other similar rules, and the float values can be retrieved to create range sliders and more, this way.
I am still fairly new to JS, and I am trying to replace the HTML of a div with a picture that is being moused over, and when the mouse leaves I want it to return to it's normal state. I thought that I did everything right but my code doesn't seem to be working. I've looked through stack overflow and I see a lot of jQuery solutions to my 'problem,' but I would like an answer in pure JavaScript (I'm trying to "maser" this first), along with an explanation so I can understand why the answer IS the answer. Thanks.
I'll try to explain myself (my code). I grabbed reference to the image holder, and I grabbed reference to the the images. I thought I made a function that looped through the array of images and added an event listener to whichever image ( image[i] ) was being moused over. Then, I added an event listener that is supposed to return the image holder to it's default state by inserting the original HTML. I just don't understand how to fix this.
var holder = document.getElementById('holder');
var images = document.getElementsByTagName('img');
var popImage = function () {
for (i = 0; i < images.length; i++) {
images[i].addEventListener('mouseover', = function () {
holder.innerHTML = images[i];
});
images[i].addEventListener('mouseout', function () {
holder.innerHTML =
'<div class='col-md-3 img-fluid' id='img1'><img src='photo1.jpg'></div>
<div class='col-md-3 img-fluid' id='img2'><img src='photo2.jpg'></div>
<div class='col-md-3 img-fluid' id='img3'><img src='photo3.2.jpg'></div>
<div class='col-md-3 img-fluid' id='img4'><img src='photo4.jpg'></div>'
});
};
};
popImage();
You said you are new to JS and just learning which is great but an important part of learning JS is learning when not to use it. As #Yoda said if this was for production you really should use CSS instead of JS.
Here is one way you could accomplish this with pure CSS
<style>
.img {
width: 100px;
height: 100px;
background: #bada55;
border: 2px solid #333;
float: left;
}
.holder:hover > .img {
opacity: 0;
}
.holder:hover > .img:hover {
opacity: 1;
}
</style>
<div class="holder">
<!-- Using div.img for simplicity, these whould be your <img/> tags -->
<div class="img">1</div>
<div class="img">2</div>
<div class="img">3</div>
<div class="img">4</div>
</div>
For the purpose of learning, here's how you'd do it in JS:
var holder = document.getElementById('holder');
var images = document.querySelectorAll('.img');
var filter = false;
function popImage () {
// Use for (var i = 0 . . .
// Instead of for (i = 0 . . .
// Because without var, i will be stored in the global scope
for (var i = 0; i < images.length; i++) {
(function (_i) {
images[_i].addEventListener('mouseover', function () {
holder.innerHTML = '';
// We can't set innerHTML to images[_i]
// because it's a DomNode not a string
holder.appendChild(images[_i]);
});
})(i);
}
holder.addEventListener('mouseout', function (e) {
if (e.target !== holder)
return;
holder.innerHTML = '';
// Again, use var j = 0 . . .
for (var j = 0; j < images.length; j++) {
holder.appendChild(images[j]);
}
});
}
popImage();
.img {
width: 100px;
height: 100px;
background: #bada55;
border: 2px solid #333;
display: inline-block;
}
#holder {
position: relative;
width: 100%;// So doesn't collape and trigger mouseout
height: 100px;
background: red;
padding: 20px 0;
}
<div id="holder">
<!-- Again, these would be your image tags -->
<div class="img">1</div>
<div class="img">2</div>
<div class="img">3</div>
<div class="img">4</div>
</div>
I had 10 mins before leaving work so I had a crack at this to see how I would do it and give you some ideas.
Here is my implementation (https://jsfiddle.net/hg7s1pyh/)
I guess the main thing here is that I've broken it down into lots of smaller parts, this makes solving problems far easier, each method is concerned with doing one thing only.
You will also note the use of classes to show and hide content rather than removing it entirely, this takes lots of the arduous work out of this feature.
function attachEvents() {
var images = getImages();
images.forEach(function(image) {
attachMouseOverEvent(image);
attachMouseLeaveEvent(image);
});
}
function attachMouseOverEvent(element) {
element.addEventListener('mouseover', function(e) {
var clonedImage = e.target.cloneNode();
addImageToPreview(clonedImage);
});
}
function attachMouseLeaveEvent(element) {
element.addEventListener('mouseleave', function(e) {
removeImageFromPreview();
});
}
function getImages() {
return document.querySelectorAll('.js-image');
}
function getImagePreviewElement() {
return document.querySelector('.js-image-box');
}
function addImageToPreview(imageElement) {
var previewElement = getImagePreviewElement();
previewElement.classList.add('previewing');
previewElement.appendChild(imageElement);
}
function removeImageFromPreview() {
var previewElement = getImagePreviewElement();
previewElement.classList.remove('previewing');
var image = previewElement.querySelector('.js-image');
image.remove();
}
attachEvents();
.image-box {
position: relative;
min-height: 400px;
width: 400px;
border: 1px solid #000;
text-align: center;
}
.image-box .placeholder {
position: absolute;
top: 50%;
text-align: center;
transform: translateY(-50%);
width: 100%;
}
.image-box.previewing .placeholder {
display: none;
}
.image-box .image {
position: absolute;
top: 50%;
text-align: center;
transform: translate(-50%, -50%);
height: 100%;
width: 100%;
}
.images {
margin-top: 10px;
}
<div class="js-image-box image-box">
<div class="placeholder">
Placeholder
</div>
</div>
<div class="images">
<div class="col-md-3 img-fluid"><img class="js-image image" src="http://placehold.it/350x150"></div>
<div class="col-md-3 img-fluid"><img class="js-image image" src="http://placehold.it/150x150"></div>
<div class="col-md-3 img-fluid"><img class="js-image image" src="http://placehold.it/400x400"></div>
<div class="col-md-3 img-fluid"><img class="js-image image" src="http://placehold.it/350x150"></div>
</div>
Am currently working with the Soundcloud API to pull images and track links for songs. Am currently showing track info through a modal window upon clicking the album image. However, for the songs on the bottom of the screen, the modal window only appears at the top of the screen, requiring a user to scroll up to see the track info. Probably has something to do with the css positioning but removing position:absolute only puts the modal window at the bottom of all the album images, requiring a scroll down. How can I make it so that a user's click on an image will open and start the modal window right where they currently are, without scrolling? Javascript / jquery /css answers all welcomed.
My CSS:
#modal {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.2);
position: absolute;
top: 0;
left: 0;
}
#trackinfo {
width:380px;
height: 180px;
padding: 20px;
margin-right: auto;
margin-left: auto;
margin-top: 100px;
box-shadow: 10px 10px 5px;
border-radius: 15px;
text-align: center;
background: #c4e5c1;
font-family: Rockwell, "Courier Bold", Courier, Georgia, Times, "Times New Roman", serif;
}
.hidden {
display:none;
}
My Javascript for show and hide modal:
function doSearch() {
var searchTerm = document.getElementById('search').value;
// Search soundcloud for artists
SC.get('/tracks', { q: searchTerm}, function(tracks) {
for(track in tracks) {
var img = document.createElement('img');
img.setAttribute("src", (tracks[track]["artwork_url"]));
var title = tracks[track].title.replace("'", "\\\'").replace("\"", "\\\"");
linky = document.createElement('a');
linky.setAttribute("href", (tracks[track].permalink_url));
console.log(linky);
img.setAttribute("onclick", "showTrackInfo('" + title + "\\n"+ tracks[track].uri + " " + "\\n\\n(click to close) " + "')");
console.log(img);
if (tracks[track]["artwork_url"] == null) {
console.log(""); }
else {
var Catalog = document.getElementById('catalog');
Catalog.appendChild(img);
$('div#catalog').append('<img src="http://i.imgur.com/rGdvfl7.png">');
}
}
});
};
function showTrackInfo(track) {
var trackInfoElement = document.getElementById("trackinfo");
trackInfoElement.appendChild(document.createTextNode(track));
var modal = document.getElementById("modal");
modal.setAttribute("class", "");
}
function hidemodal() {
var trackInfoElement = document.getElementById("trackinfo");
trackInfoElement.childNodes;
while ( trackInfoElement.firstChild ) trackInfoElement.removeChild( trackInfoElement.firstChild );
var modal = document.getElementById("modal");
modal.setAttribute("class", "hidden");
}
The functions all work well, I just need to know how to position the modal box upon click so that the user doesn't need to scroll to see the trackinfo. Any help much appreciated.
Try position: fixed; on the dialog box, should make it fill the page no matter where they are on it