I am trying to use JavaScript so when you click on the menubars icon, the whole menu appears when opening the website on a phone using Google. (when device width is larger than 470px, menubars have a display: none)
This is the necessary html:
<div id="menu">
<i class="fa fa-bars" aria-hidden="true" style='font-size:36px; color: white' id="menubars"></i>
<nav>
Home
Projects
Contact
</nav>
</div>
This is the css:
#media only screen and (max-width: 470px) {
body{
background-image: none;
}
#menu {
position: absolute;
display: flex;
flex-direction: row-reverse;
justify-content: flex-end;
z-index: 3;
padding-bottom: 30px;
padding-right: 5px;
width: 75%;
background-color: black;
transform: translate(-195px, 0);
}
#menubars {
display: initial;
}
and this is the JS:
const menubars =document.getElementById("menubars");
const menu = document.getElementById("menu");
menubars.addEventListener("touch", function() {
menu.style.borderRight = "white thin";
menu.style.transform = "translate(195px)";
});
I know the script is linked correctly because I can see the event listener when clicking inspect element.
website opened with devtools
The website is :
https://maria-shn.github.io/Portfolio
I am new to JS and I know there is probably a better way to achieve my goal but I would like to understand why it is not working.
AFAIK there is no touch event, there are touchstart, touchend, touchmove and touchcancel. If you put a breakpoint inside your event handler, you can see it is never triggered. (maybe try first with click event, since this is hidden on desktop anyway...)
The border-right value is missing what kind of line you want to present (solid, dashed, etc.) (explanation)
Not sure if this is what you intended, but translate(195px) will translate both the X and Y positions, you can use translateX() (or Y) to move just one
we don't have touch event, you can see about touchcancel, touchend, touchmove, touchstart. We can start testing by click.
Related
My layout looks almost identical to this codepen.
.parent {
color: white;
padding: 70px;
position: relative;
background-color: #0074d9;
margin-top: 50px;
}
.element {
background-color: lighten(#0074d9, 20);
opacity: .85;
padding: 20px;
color: rgba(255,255,255,.9);
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
The codepen works the right way, so it's been hard to come up with a demonstrable example.
When my cursor is positioned over the fixed "child element" div, I want to be able to scroll the parent but not be able to clickthrough.
The common answer seems to be "pointer-events: none", but that allows click interaction with the page below.
Open to other suggestions or explanations as to why it works in the codepen, but doesn't outside of it.
The solution that worked for me was to use jquery to grab the parent by id and add my deltaY to its scrollTop.
<div
onWheel={(e) => {
const component = $(`#content`);
const contentScrollPosition = component.scrollTop();
component.prop("scrollTop", contentScrollPosition + e.deltaY);
}}
</div>
This allows me to scroll the parent even when my cursor is on the fixed-position div.
Unfortunately, mobile doesn't work well. First, you would need to track the touch event though onTouchStart, End, and Move. Even then, you lose touch scroll momentum which makes it feel too unnatural.
I just found this and can't explain myself why it behaves like this. But this is exactly the behavior I want to implement. Try this example:
const redBar = document.querySelector("#red");
const greenBar = document.querySelector("#green");
redBar.onmousemove = moveHandle;
redBar.onclick = moveHandle;
greenBar.onmousemove = moveHandle;
greenBar.onclick = moveHandle;
function moveHandle(event) {
if (event.buttons === 1 || event.type === "click") {
let y = (event.y - this.offsetTop) - 7.5;
if (y < -7.5) {
y = -7.5;
} else if (y > this.offsetHeight - 7.5) {
y = this.offsetHeight - 7.5;
}
this.querySelector(".handle").style.top = y + "px";
}
}
body {
display: flex;
width: 100vw;
height: 100vh;
justify-content: center;
align-items: center;
margin: 0;
}
.container {
display: flex;
flex-direction: row;
}
.bar {
position: relative;
background: red;
overflow: visible;
margin: 30px;
width: 30px;
height: 200px;
}
.no-overflow {
background: green;
overflow: hidden;
}
.handle {
position: relative;
width: 60px;
height: 15px;
top: -7px;
left: -15px;
background: #222d;
}
<div class="container">
<div id="red" class="bar">
<div class="handle"></div>
</div>
<div id="green" class="no-overflow bar">
<div class="handle"></div>
</div>
</div>
Try moving the handle of the red bar and of the green bar. On the green bar you can move the handle once you had the mouse down on the bar and keep holding down the button, even if you are not above the bar.
The only difference is that on the green one (except the color) the overflow
is hidden.
Is this a bug or did I forget something? (I'm on Firefox btw)
And whats the best way to implement a behavior like this without the overflow being hidden because when i try to do this, it always get pretty messy. (I know there are sliders but maybe in case I want something like this with 2 dimensions)
Thanks!
UPDATE
By further testing, I noticed that this stops working when user-select is none. Then it behaves like the element without the hidden overflow.
The mousemove misfiring in Firefox due to overflow:hidden looks like bug 620513 / bug 1352061.
As for achieving this effect without relying on the bug, Teemu correctly notes that:
Usually this is done by listening mousedown on the element, and when that fires, stop listening mousedown and start to listen mouseup and mousemove on document. When mouseup fires, stop listening mouseup and mousemove, and start listening mousedown on the element again.
Pointer Events API (.setPointerCapture()) is the modern way to achieve this behavior (needs a polyfill for Safari and older browsers).
I have a simple 3 column layout with a left sidebar, content area, and right sidebar. I am using flexbox to handle widths. I would like to make it so that when a user drags the right border of the left sidebar, the div can be resized. I would prefer a css solution if it makes sense but am open to javascript or jquery. Whichever approach is easiest for me to understand : )
Here is a possible solution using the css resize property (click Run code snippet to see the result).
Notes:
The resize handler is in the bottom right corner of the left sidebar
The resize property is not yet fully supported by all browser (~74% see caniuse)
The styles for the resize handler are still limited (see this question)
.container {
height: 500px;
display: flex;
}
.left-sidebar {
display: flex;
flex-direction: row;
background-color: #364F6B;
color: #fff;
/* This is for resizing */
overflow: scroll;
resize: horizontal;
}
.center-aria {
background-color: #3FC1C9;
flex-grow: 2;
}
.right-sidebar {
background-color: #FC5185;
}
.left-sidebar, .right-sidebar, .center-aria {
padding: 8px;
}
<div class="container">
<div class="left-sidebar">
Left Sidebar - Resize me
</div>
<div class="center-aria">Center Aria</div>
<div class="right-sidebar">Right Sidebar</div>
</div>
I have a element (it is an icon) with onClick event. I want to show that element only if certain criteria is met and I'm able to read that criteria and handle the show/hide completely from CSS.
If the element is visible and I click on it, I want it to make two actions:
trigger JS event,
hide the element.
But CSS hides the element somehow quicker than JS can respond and the event is simply not triggered.
I did not studied how the the event system in JS works, but it seems to me, that firstly the CSS is resolved and then the JS event system receives info about click event on certain x/y position, where the element is no more, so the event is not triggered.
I tried several CSS options to hide the element including this CSS properties:
display: block / none;
visibility: visible / hidden;
z-index: 1 / -1;
width|height: auto / 0;
top|left|right|bottom: 0 / -9999px;
If I hide the element with opacity: 1 / 0, the event is triggered, because the element remains clickable in place, where it resides, but that is also problem, because I do not want the element to be clickable if not visible.
Is there any hack, how to hide element via pure CSS and at the same time trigger event on it?
I tried delay the CSS with transition: all 160ms;, but the CSS rules, that hides the element, are instant (you cannot transition display, visibility or z-index) so this had no use.
I challenge this problem in Google Chrome 53.0.2785.116 platform Win10 x64
EDIT : JSBin
Problem with click is when the item is hidden, the click action can not be completed. So you can switch to mousedown instead of click
document.getElementById("test_click").addEventListener("mousedown", function(){
console.log("Clicked");
});
#test_container {
position: relative;
display: inline-block;
}
#test_click {
position: absolute;
display: none;
left: 100%;
top: 50%;
}
#test_input:focus + #test_click {
display: inline;
}
#test_input:focus + #test_click:hover {
color: dodgerblue;
cursor: pointer;
}
<div id="test_container">
<input type="text" id="test_input" placeholder="focus me...">
<span id="test_click">CLICK</span>
</div>
<h3>Click on the input and "CLICK" appears, click on "CLICK" and "CLICK" hides and no JS event is triggered although it is attached. Then, remove "display: none;" from CSS and try click again, the JS event is triggered.</h3>
or add css to keep element visible when hovered
document.getElementById("test_click").addEventListener("click", function(){
console.log("Clicked");
});
#test_container {
position: relative;
display: inline-block;
}
#test_click {
position: absolute;
display: none;
left: 100%;
top: 50%;
}
#test_click:hover,
#test_input:focus + #test_click {
display: inline;
}
#test_input:focus + #test_click:hover {
color: dodgerblue;
cursor: pointer;
}
<div id="test_container">
<input type="text" id="test_input" placeholder="focus me...">
<span id="test_click">CLICK</span>
</div>
<h3>Click on the input and "CLICK" appears, click on "CLICK" and "CLICK" hides and no JS event is triggered although it is attached. Then, remove "display: none;" from CSS and try click again, the JS event is triggered.</h3>
How can I be able to scroll article while having my mouse cursor over .header while still having .header clickable? If I set z-index: -1 to .header I'm able to scroll while having the cursor over .header, but it's no longer clickable.
Demo
Fiddle
HTML:
<div class="row">
<div class="off-canvas-wrap">
<div class="inner-wrap">
<div class="header">
I should be clickable
</div>
<article class="small-12 columns">
<div style="height:5000px">
</div>
</article>
</div>
</div>
</div>
CSS:
article {
overflow-y: auto;
}
article,
body,
html,
.off-canvas-wrap,
.off-canvas-wrap .inner-wrap,
.row {
height: 100%;
width: 100%;
}
.header {
position: absolute;
width: 400px;
height: 400px;
background: #000;
left: 50%;
top: 50%;
margin-left: -200px;
margin-top: -200px;
z-index: 1;
color: #fff;
text-align: center;
padding-top: 1em;
}
If you want a CSS solution, there is none — this is because of how mouse events are directly related to the visibility of the item to the pointer/cursor: e.g. if you place .header in the back such that it is not accessible (so that scroll events on article can be triggered), it will not register a click event, too.
A JS-based solution would be listening to the mousewheel() event (with this plugin, available as a CDN-hosted plugin, too) and then manually triggering scrolling on the article element. However, this does not replicate the default scrolling behavior on individual OSes, and may appear choppy on OSes that has smoothed scrolling events (like OS X).
Without further ado:
// Cache article's position from top (might change if the page is loaded with a hash, so we cannot declare it as 0)
var fromTop = $('article').scrollTop();
$('.header').mousewheel(function(e,d) {
// Prevent default scrolling behavior, even when .header is overflowing
e.preventDefault();
// Trigger scroll in window
// You can change how much to amplify the 'd', which is the delta (distance registered from the scrollwheel). I have chosen it to multiply it by 10
fromTop = fromTop - d*10;
$(this).next('article').scrollTop(fromTop);
}).click(function() {
// Just testing
alert('Header is clicked on!');
});
Here is the proof-of-concept JSFiddle: http://jsfiddle.net/teddyrised/CK7z8/2/
Warning: In the event that there are multiple .header elements targeting multiple article elements on the same page, you will have to iterate through each .header-article pair and cache the fromTop separately for each pair.