While focus the element, page not get scrolled in firefox and IE? - javascript

I have tried to focus the element in my page using focus method. When the element is focusing, page scrolled automatically in to the focused element. But In firefox and IE browsers page not scrolled properly. So my focused element visible in bottom of the page.
Steps:
Run the sample in chrome, element will be appear in middle of the page.
In Firefox it will appear in bottom of the page.
How to resolve it?
setTimeout(() => {
document.getElementById('parent-element').focus();
}, 10);
body {
touch-action: none;
}
#target {
height: 2000px;
background-color: aliceblue;
}
#parent-element {
max-height: 980px;
width: 400px;
left: 150px;
top: 958px;
display: inline-flex;
background-color: #fff;
box-shadow: 0 12px 40px 5px rgba(0, 0, 0, 0.26);
max-width: 100%;
min-width: 240px;
height: auto;
position: absolute;
}
.Child-element {
border-bottom: none;
padding: 18px;
border-radius: 1px 1px 0 0;
line-height: 30px;
background-color: #fff;
}
.childcontent {
display: block;
width: 83%;
color: rgba(0, 0, 0, 0.87);
}
<div id="target">
<div id="parent-element" role="dialog" tabindex="-1">
<div class="Child-element">
<div class="childcontent">Am developer</div>
</div>
</div>
</div>

I can offer an experimental alternative solution I found while trying to figure out why Firefox doesn't center on focus().
scrollIntoView() will work for you if all you want to do is scroll the div into the center of the page. Again, its experimental, but I tested it in the latest Chrome and Firefox browsers and it works there.
You can use the following:
document.getElementById('parent-element').scrollIntoView({behavior: "instant", block: "center"});
You can check browser compatibility from these two resources. MDN and Can I Use

Related

How can I toggle or hide CSS pseudo-elements on event (e.g., click)?

Background
I have an HTML div which contains a ‘tooltip’-like feature (i.e., a text box pops up when a certain element is clicked or hovered over); this tooltip has decorative pseudo-elements to make it look like a ‘speech bubble,’ added in css as :before and :after .
I have a JS script, which is intended to show and hide the tooltip and decoration, in response to click events (i.e., toggle them between ‘show’ and ‘hide’ states).
Problem
I can’t get the decorative pseudo-elements to hide when the tooltip is hidden; as pseudo-elements, they are not part of the DOM and so I can’t use normal selectors to manipulate them.
When the tooltip is hidden on click, the decorative pseudo-elements persist, which is not a usable result.
I can’t do away with the decorative elements, they are part of the work specification.
Approach tried so far
Based on this question, my thought was to add an empty span with its own class, to which I’d prepend and append these pseudo-elements. Then, add or remove the class on click based on whether it exists already, or not.
I have also tried setting the class to which the pseudo-elements are pre/appended to display:none on click, but this also seems not to work
However, I cannot convince the pseudo-elements to hide on click.
I’ve included a screenshot of what these remnant pseudo-elements look like in the live environment.
Note: I tried to work up a running simulation for the purpose of this question, but I wasn’t able to and the original css file is massive; the code included below is for reference only.
All guidance is much appreciated!
const barContainer = document.querySelector(".bar-container");
const decorationElement = document.querySelector("#decoration");
document.addEventListener('click', function(event) {
console.log('click event listener triggered');
if (event.target.closest('.link') || event.target.classList.contains('link')) {
if (barContainer.classList.contains('open')) {
barContainer.classList.remove('open')
decorationElement.classList.remove('decoration')
document.querySelector('.tooltip-container').setAttribute('style', 'display:none');
} else {
barContainer.classList.add('open')
decorationElement.classList.add('decoration')
document.querySelector('.tooltip-container').setAttribute('style', 'display:block');
}
} else {
barContainer.classList.remove('open')
decorationElement.classList.remove('decoration')
document.querySelector('.tooltip-container').setAttribute('style', 'display:none');
}
});
.foo-container {
height: auto;
position: relative;
}
.bar-container {
height: auto;
position: relative;
text-align: center;
}
.bar-container:hover .tooltip-container,
.tooltip-container:hover,
.bar-container.open .tooltip-container {
position: absolute;
display: block;
text-align: left;
background-color: #ffffff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
bottom: 50px;
right: 5%;
border-radius: 4%;
font-weight: 300;
max-width: 90%;
font-size: 14px;
padding: 20px 0;
}
/*the below two rule sets create the rotated 'decoration' */
.bar-container:hover .tooltip-container:before,
.tooltip-container:hover:before,
.bar-container.open .tooltip-container:before,
.foo-container .bar-container:hover .decoration:before {
content: "";
width: 65px;
height: 35px;
position: absolute;
overflow: hidden;
transform: rotate(-180deg);
z-index: 10;
bottom: 0;
left: 170px;
background-color: white;
}
.foo-container .bar-container.open .decoration:before,
.foo-container .bar-container:hover .decoration:before {
content: "";
position: absolute;
width: 30px;
height: 30px;
background: #fff;
transform: rotate(45deg);
left: 30px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
z-index: 2;
top: -42px;
}
/* end 'deocration' */
<div class="foo-container">
<div class="bar-container">
<p>text <span class='link'>the-link<span id='decoration' class='decoration'></span></span>
</p>
<div class='tooltip-container'>
<p>lorem </p>
</div>
</div>
</div>
Screenshot of the undesirable 'persistent pseudo-elements' behavior -->

Vertically Draggable Division of Two Areas

I want to make a vertically draggable division of two areas like the following.
I just want to modify a online example of draggable divs to be what I want. Finally, I got this. Can someone give me some hints to modify it?
JSFiddle Link : https://jsfiddle.net/casperhongkong/omekvtka/14/
HTML
<div class="container">
<div class="area1">
Area 1
</div>
<div class="drag">
</div>
<div class="area2">
Area 2
</div>
</div>
CSS
.container {
position: fixed;
top: 51px;
right: 0px;
bottom: 0px;
left: 0px;
background-color: #272822;
border: 1px solid #222;
// margin: 0 auto;
//display: inline-block;
}
.area1 {
position: absolute;
height: 100%;
width: 30%;
background-color: #ddd;
display: inline-block;
}
.drag {
position: fixed;
width: 5px;
height: 100%;
background-color: #444;
display: inline-block;
}
.area2 {
position: absolute;
right: 0;
height: 100%;
width: 30%;
background-color: #ddd;
display: inline-block;
}
JavaScript
$(document).ready(function() {
$('.drag').on('mousedown', function(e) {
var $area1 = $('.area1'),
$area2 = $('.area2'),
startWidth_a1 = $area1.width(),
startWidth_a2 = $area2.width(),
pX = e.pageX;
$(document).on('mouseup', function(e) {
$(document).off('mouseup').off('mousemove');
});
$(document).on('mousemove', function(me) {
var mx = (me.pageX - pX);
$area1.css({
width: startWidth_a1 - mx;
});
$area2.css({
//left: mx / 2,
width: startWidth_a2 - mx,
//top: my
});
});
});
});
For javascript, I would recommend checking out a library, as this is slitghtly more complicated than just a few lines. #fauxserious gave Split.js as a fantastic example.
This is possible in pure HTML/CSS, though slightly limited, as discussed here.
HTML:
<div class="split-view">
<div class="resize-x panel" style="width: 216px;">
Panel A
</div>
<div class="panel">
Panel B
</div>
</div>
CSS:
/* Panels: */
.panel{
padding: 1em;
border-width: 6px;
border-style: solid;
height: 4em;
}
/* Resizing */
.resize-x {
resize: horizontal;
overflow: auto;
}
/* Split View */
.split-view {
margin: 1em 0;
width: 100%;
clear: both;
display: table;
}
.split-view .panel {
display: table-cell;
}
Based on #afischer's table-cell solution, here is an alternative one.
I have had to put accordions within the left side panel.
The sticky headers of the accordions require overflow to be visible,
while resize requires overflow to be anything but visible:
https://caniuse.com/#feat=css-sticky.
In the same time, I didn't need anything to place into the right side panel.
Thus, an overcome was employing resize on the right panel, and rotating by 180 deg to get the dragable side to the middle, as well as this way the dragable corner relocated to the top (visible without scrolling).
Plus some highlight has been added to the dragable corner.
/* Panels: */
.panel{
padding: 1em;
border-width: 6px;
border-style: solid;
height: 4em;
}
/* Resizing */
.resize-x {
resize: horizontal;
overflow: auto;
transform: rotate(180deg);
border-right: solid gray 1px;
}
/* Split View */
.split-view {
margin: 1em 0;
width: 100%;
clear: both;
display: table;
}
.split-view .panel {
display: table-cell;
}
.resize-x::-webkit-resizer {
border-width: 8px;
border-style: solid;
border-color: transparent orangered orangered transparent;
}
<div class="split-view">
<div
class="panel"
style="width: 216px;">
Panel A
</div>
<div class="panel resize-x">
Panel B
</div>
</div>
Unfortunately there are two disappointing thing with the above:
Firefox cannot handle the combination of table-cell and resize
Only a corner of the grabber is responsive, which can even be scrolled out easily
Here is an other solution which also takes the above two problems into account
without resize CSS property
and with full height responsive grabber
It's a combination of a flexbox and an input:range slider.
The trick is that the pointer-event CSS property can be different
on the slider's background
and on its grabber.
The slider covers the entire view. The background of the slider is transparent for the events too (pointer-events: none), while the dragbar itself catches the events (pointer-events: auto).
It requires minor Javascript and because I've implemented the production version in Nuxt.js, I use Vue.js here, instead of vanilla JS.
new Vue({
el: '#vue',
data: {
windowWidth: null,
splitWidth: null,
},
mounted() {
this.windowWidth = window.innerWidth;
// For arbitrary initial position:
this.splitWidth = this.windowWidth * 2/3;
},
computed: {
flexRatio() {
return this.splitWidth / this.windowWidth;
}
}
})
body {
margin:0;
}
main {
display: flex;
width: 100%;
height: 100vh;
}
article {
display: flex;
}
section {
width: 100%;
height: 100%;
text-align: justify;
padding: 20px;
}
.section-left {
background-color: darkseagreen;
}
.section-right {
background-color: orangered;
}
#split-grabber {
pointer-events: none;
position: fixed;
top: 0; right: 0; bottom: 0; left: 0;
-webkit-appearance: none;
/* Safari allows dragging behind scroll bar.
We fix it by shrinking its width on the right side via both
its range value :max="windowWidth - 12"
and its width (CSS) width: calc(100% - 12px)
...synchronously */
width: calc(100% - 12px);
height: 100vh;
background: transparent;
outline: none;
margin: 0;
}
#split-grabber::-webkit-slider-thumb {
z-index: 1;
pointer-events: auto;
-webkit-appearance: none;
appearance: none;
width: 5px;
height: 100vh;
background: lightgray;
box-shadow: 1px 2px 2px 0px gray;
cursor: col-resize;
}
#split-grabber::-moz-range-thumb {
z-index: 1;
pointer-events: auto;
-webkit-appearance: none;
appearance: none;
width: 5px;
height: 100vh;
background: lightgray;
box-shadow: 1px 2px 2px 0px gray;
cursor: col-resize;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<main id="vue">
<!-- Safari allows dragging behind scroll bar
We fix it by shrinking its width on the right side via both
its range value :max="windowWidth - 12"
and its width (CSS) width: calc(100% - 12px)
...synchronously -->
<input
id="split-grabber"
type="range"
v-model="splitWidth"
:max="windowWidth - 12"
>
<article
class="article"
:style="{'flex': flexRatio}"
>
<section
class="section section-left">
splitWidth:{{ splitWidth }}px<br>
“There was a rich man who always dressed in the finest clothes and lived in luxury every day.
And a very poor man named Lazarus, whose body was covered with sores, was laid at the rich man’s gate.
He wanted to eat only the small pieces of food that fell from the rich man’s table. And the dogs would come and lick his sores.
Later, Lazarus died, and the angels carried him to the arms of Abraham. The rich man died, too, and was buried.
In the place of the dead, he was in much pain. The rich man saw Abraham far away with Lazarus at his side.
He called, ‘Father Abraham, have mercy on me! Send Lazarus to dip his finger in water and cool my tongue, because I am suffering in this fire!’
</section>
</article>
<article
class="article"
:style="{'flex': 1-flexRatio}"
>
<section class="section section-right">
But Abraham said, ‘Child, remember when you were alive you had the good things in life, but bad things happened to Lazarus. Now he is comforted here, and you are suffering.
Besides, there is a big pit between you and us, so no one can cross over to you, and no one can leave there and come here.’
The rich man said, ‘Father, then please send Lazarus to my father’s house.
I have five brothers, and Lazarus could warn them so that they will not come to this place of pain.’
But Abraham said, ‘They have the law of Moses and the writings of the prophets; let them learn from them.’
The rich man said, ‘No, father Abraham! If someone goes to them from the dead, they would believe and change their hearts and lives.’
But Abraham said to him, ‘If they will not listen to Moses and the prophets, they will not listen to someone who comes back from the dead.’”
</section>
</article>
</main>

JS not working after doing custom css on Wordpress Site

I am currently in the process of developing an online shop via wordpress. Everything was working fine, now I wanted to give my page a custom border( inverted round corners) and found the css code for it as seen here:
css:
body {
background-color: #fff;
}
.wrapper {
overflow:hidden;
width:200px;
height:200px;
}
div.inverted-corner {
box-sizing:border-box;
position: relative;
background-color: #3e2a4f;
height: 200px;
width: 200px;
border: solid grey 7px;
}
.top, .bottom {
position: absolute;
width: 100%;
height: 100%;
top:0;
left:0;
}
.top:before, .top:after, .bottom:before, .bottom:after{
content:" ";
position:absolute;
width: 40px;
height: 40px;
background-color: #fff;
border: solid grey 7px;
border-radius: 20px;
}
.top:before {
top:-35px;
left:-35px;
}
.top:after {
top: -35px;
right: -35px;
box-shadow: inset 1px 1px 1px grey;
}
.bottom:before {
bottom:-35px;
left:-35px;
}
.bottom:after {
bottom: -35px;
right: -35px;
box-shadow: inset 1px 1px 1px grey;
}
html:
<div class="wrapper">
<div class="inverted-corner">
<div class="top"> </div>
<h1>Hello</h1>
<div class="bottom"> </div>
</div>
</div>
I renamed the classes to get no conflict with the existing css classes of the theme. It is working fine as seen here:my site. The problem is now, that I cannot interact with the site anymore, no links, no hover effects. It seems like the custom css is overlaying the actual site. Do you have any suggestions what I maybe did wrong?
P.S. I edited the header.php so that inverted corner div and the top div are right underneath the page-wrapper div( site content) and in the footer.php I edited the top div and the inverted-corner div closing right above the page-wrapper div closing.
Add :
pointer-events: none;
to the .bottom-corner CSS, so the mouse passes through.
In your custom.css you have this:
.top-corner, .bottom-corner {
position: absolute;
width: 100%;
height: 100%;
top:0;
left:0;
}
This basically overlays the whole page and thus disables any interaction.
One other option I would like to suggest to change following css rule
CSS
.top-corner, .bottom-corner {
position: absolute;
width: 100%;
height: 100%;
top:0;
left:0;
}
Replace above code with the below one
.top - corner, .bottom - corner {
position: absolute;
width: 100 % ;
}
this solution will work on all modern browsers and IE8 and above ( I'm not sure about lower version of IE, but it may work on them as well )

Disable Anchor Within Hover Div on Mobile Until Open

I've searched high and low but can't find a solution to this exact problem.
On a desktop browser, when the user hovers over an image, a div appears and they can click the link within the div if they want. However, on a mobile device, the hover is triggered by a click. If the user clicks in just the right spot, even though the div isn't visible yet, they can accidentally click the anchor and navigate away from the page. (In other words, the div goes from display:none to display:block at the same time that the link is clicked.)
I want to prevent that accidental click from happening on mobile browsers, however I still want the link to be usable once the div is visible.
My code:
<style>
.staffpic {
position: relative;
width: 33.33333%;
height: auto;
}
.staffpic:hover .popup {
display: block;
}
.staffpic img {
display: block;
width: 110px;
height: 110px;
margin: 0 auto;
}
.popup {
display:none;
position: absolute;
bottom: 0;
left: -5px;
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 15px;
background-color: rgba(255, 153, 0, 0.9);
color: #fff;
text-transform: uppercase;
}
</style>
<div class="staffpic">
<img src="/wp-content/uploads/image.jpg" />
<div class="popup">
John Smith, Director<br/>
CityName | Email John
</div>
</div>
Any ideas? HTML, CSS, JS and jQuery solutions are all welcome! (Maybe something more clever than what I can think of using pointer-events:none along with some jQuery?)
I'm actually about to encounter the same problem in a project, and jotted down a potential solution. Haven't tested it yet but it might help you out. The link should only trigger if the element has a display that's not 'none':
var popup = $('.popup'),
display = popup.css('display');
if (!(display === 'none')) {
popup.on('click', function(e) {
e.preventDefault();
});
}
I found a solution but it's not elegant. I wanted to post it in case someone has this problem in the future and just needs something that will work!
I added a fake link in a span with the real link then set new display styles for it and the real link based on the parent span is being hovered over.
<style>
.staffpic {
position: relative;
width: 33.33333%;
height: auto;
}
.staffpic:hover .popup {
display: block;
}
.staffpic img {
display: block;
width: 110px;
height: 110px;
margin: 0 auto;
}
.staffpic a {
display: none; /* Added */
}
.staffpic.link:hover a {
display: inline; /* Added */
}
.staffpic.link:hover .fakelink {
display: none; /* Added */
}
.popup {
display:none;
position: absolute;
bottom: 0;
left: -5px;
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 15px;
background-color: rgba(255, 153, 0, 0.9);
color: #fff;
text-transform: uppercase;
}
</style>
<div class="staffpic">
<img src="/wp-content/uploads/image.jpg" />
<div class="popup">
John Smith, Director<br/>
CityName | <span class="link">Email John<span class="fakelink">Email John</span></span>
</div>
</div>
I'd still love a cleaner solution without all this added html if someone has it.

Overlay is clickable through an element in front of it

I am using an overlay for a login which appears in front of everything when the user hit "sign-in". The overlay consists of an opaque wrapper which contains a solid inner-div where the login form is held.
Here is the html:
<div class="login_wrapper">
<div class="login_info">
<div class="login_form">
// form
</div>
</div>
</div>
and the css:
.login_wrapper{
position:absolute;
position: fixed;
margin: auto;
left:0;
right: 0;
top: 0;
bottom: 0;
width: 100%;
height:100%;
background-color:rgba(0, 0, 0, 0.5);
z-index:9998;
display: none;
}
.login_info{
font-family: "NimbusCondensed";
position:absolute;
margin: auto;
left:0;
right: 0;
top: 0;
bottom: 0;
width: 350px;
height:300px;
background: #cacaca;
border: solid #000000 1px;
border-radius: 10px;
z-index:99999;
pointer-events: none;
}
.login_form{
margin-top: 40px;
margin-left: 12.5%;
padding: 10 20 0 20;
width: 220px;
border: 1px solid black;
border-radius: 7px;
background: white;
box-shadow: 0px 5px 13px black;
z-index: 100000;
}
I would like this overlay to be hidden when the user clicks anywhere outside of the login_info.
I have the following JQuery handling this:
$(document).ready(function(){
$(".login_wrapper").click(function(){
$(".login_wrapper").fadeToggle(300);
});
});
But login_wrapper is hidden if the use clicks ANYWHERE on the overlay, including the form in the middle which prevent then form entering any info.
Somehow the click events are getting "through" login_form & login_info and the browser reacts like login_wrapper is clicked.
How can I resolve this so that jQuery code applies ONLY when the overlay is clicked outside the inner divs.
Thanks!
Change your code to this:
$(document).ready(function(){
$(".login_wrapper").click(function(){
$(".login_wrapper").fadeToggle(300);
});
$(".login_info").click(function(event){
event.stopPropagation();
});
});
This will stop the click event from bubbling up to the .login_wrapper. For more information on stopPropagation() see https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation.
First, you have to transform .login_wrapper in #login_wrapper, then add this:
$('#login_wrapper').click(function(e) {
if (e.target.id === "login_wrapper")
$('#login_wrapper').fadeToggle(300);
});
This will target only the element with the id login_wrapper.
Hope this helps

Categories