Can't close popup with touch without a specific button in ios - javascript

I am learning now how to create popups in mobile devices, and I created a popup that closes when I touch any part of the screen, but it doesn't work on ios (maybe on all touch devices, haven't checked), only on the computer.
Now based on the information I read here:
jQuery click events not working in iOS
Make onclick work on iphone
How to bind 'touchstart' and 'click' events but not respond to both?
Cannot close popup() window in iPhone Safari
The popup opens fine because you press a link attribute <a> to open it up, however upon closing I can press any part of the screen.
Here is the code:
var modal = document.getElementById('myModal'); // Get the popup
var btn = document.getElementById("myBtn"); // Get the button that opens the popup
btn.onclick = function() { // Open the popup
modal.style.display = "block";
}
window.onclick = function(event) { // Closes the popup
if (event.target == modal) {
modal.style.display = "none";
}
}
I tried adding cursor: pointer; in CSS, changing the script in javascript to onmouseover instead of click, changing the script, changing window.click to div.click and adding the following code to the javascript script:
let touchEvent = 'ontouchstart' in window ? 'touchstart' : 'click';
window.on(touchEvent, function(event){...});
Nothing worked...
I guess I don't quite get how to use the touch event listener, if it's connected.

You need to add event listeners for touchstart and/or touchend for this to work on mobile devices, check out the snippet below:
// JavaScript
var modal = document.getElementById('myModal'); // Get the popup
var btn = document.getElementById("myBtn"); // Get the button that opens the popup
btn.onclick = function() { // Open the popup
modal.style.display = "block";
}
let eventsArray = ["click","touchstart", "touchend"];
eventsArray.forEach( function(event) {
window.addEventListener(event, function(e) {
if (e.target === modal) {
modal.style.display = "none";
}
}, false);
});
/*CSS*/
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#myModal {
display: none;
position: fixed;
top: 0;
left: 50%;
transform: translateX(-50%);
background-color: rgba(0, 0, 0, 0.25);
width: 100%;
height: 100%;
text-align: center;
}
#myModal span {
position: fixed;
top: 50%;
left: 50%;
padding: 10px;
background-color: #a600a6;
color: #fff;
transform: translate(-50%, -50%);
}
<!--HTML-->
<body class="overlay">
<div >
<button id="myBtn">
Open Modal
</button>
</div>
<div id="myModal">
<span>Hello World!</span>
</div>
</body>
Tested on jsfiddle with an iPad and it works.

Related

Why do i have to click twice to open a modal?

I am trying to make a button on which if we click a popup opens(modal) and it is working but only problem is i need to click it twice to open it and i don't see how can i solve it.
// Get the modal
function modal1() {
var modal = document.getElementById("myModal");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
}
/* The Modal (background) */
.modal {
display: none;
/* Hidden by default */
position: fixed;
/* Stay in place */
z-index: 1;
/* Sit on top */
padding-top: 100px;
/* Location of the box */
left: 0;
top: 0;
width: 100%;
/* Full width */
height: 100%;
/* Full height */
overflow: auto;
/* Enable scroll if needed */
background-color: rgb(0, 0, 0);
/* Fallback color */
background-color: rgba(0, 0, 0, 0.4);
/* Black w/ opacity */
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
/* The Close Button */
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
<!-- Trigger/Open The Modal -->
<button id="myBtn" onclick="modal1()">Open Modal</button>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..</p>
</div>
</div>
Thank you in advance :)
ps: I am leaning in very early stage js (beginner)
It's fairly straightforward if you read your code in order.
When you click the button, it runs the modal1() function.
This function, among other things, adds a btn.onclick listener, waiting for a click.
That's it.
So now, you have to click a second time in order to trigger the listener you just created.
The new onclick listener you create, for that matter, overrides the current onclick on the button, and I'm not sure why you do this.
The simple solution is to put modal.style.display = "block" directly in modal1(). Why override the onclick function?
function modal1() {
modal.style.display = "block";
}

Javascript code is getting executed even before user presses ok on alert window

I need to remove video element, Canvas and a button on canvas before displaying an alert window and once user presses ok button on the alert window, I need to display some other elements. Currently I am facing below issues.
alert window is getting displayed before deleting the button. So we
just used setTimeout to delete all the elements before displaying
alert window to fix this.
The UI code which should be executed after user presses 'ok' button
is getting executed after alert window display with out stopping for
user click. I thought that the code next to alert() should not be
executed until user presses Ok on alert window.
Below is Javascript code.
$("#remoteVideo").remove();
$("#localCanvas").remove();
$(".terminate_session_btn").remove();
// USED setTimeout TO DELAY THE DISPLAY OF ALERT WINDOW. WITHOUT
// setTimeout, ALERT WINDOW IS GETTING DISPLAYED BEFORE DELETING THE BUTTON.
setTimeout(function() {
displayAndProcessUserTerminateAlertDialog();
}, 200);
function displayAndProcessUserTerminateAlertDialog() {
socket.close();
alert("User terminated the video call. Press 'Ok' button to create new session.");
// BELOW CODE IS GETTING EXECUTED WITHOUT STOPPING FOR USER ACTION ON ALERT WINDOW.
$(".main_container .item").hide();
$("#video-session-menu").removeClass("active");
$("#images-menu").removeClass("active");
$(".sidebar ul li a").addClass("disabled");
}
Can anyone please help me to understand why code execution is not stopped until user presses OK on alert window and how to fix this issue.
UPDATE:
Interesting thing is if I open developer tools, the issue is not happening. If I don't open developer tools, issue is happening always. I am not sure how to fix this issue.
Apparently browsers do not have a standard behavior for alert. As a result, you might want to implement your own alert with the behavior you prefer. You can test it here: https://jsfiddle.net/rf0jd7te/1/
HTML
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>Alert Window</p>
<p>
<input type="button" value="OK">
</p>
</div>
</div>
CSS
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content/Box */
.modal-content {
background-color: #fefefe;
margin: 15% auto; /* 15% from the top and centered */
padding: 20px;
border: 1px solid #888;
width: 80%; /* Could be more or less, depending on screen size */
}
/* The Close Button */
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
JS
console.log("before alert");
var modal = document.getElementById("myModal");
// Get the <span> element that closes the modal
var span = modal.getElementsByClassName("close")[0];
// Get the OK element that closes the modal
var OK = modal.querySelector("input[type=button]");
// When the user clicks on <span> (x), close the modal
function close() {
modal.style.display = "none";
console.log("after alert");
}
OK.onclick = span.onclick = function() {
close();
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
close();
}
}
modal.style.display = "block";
Alert in JS is only responsible for showing message, try to use window.confirm(message) (check example use case)

div loses focus, when clicked on a child which has focus

So, I am making a modal which has focus on it when it is shown.
And if the user clicks outside, I want to hide it.
I have implemented this with the help of focus events.
In cases, where the modal itself has a child which is focusable, modal loses the focus, I have also handled it in the below code. These cases are correctly handled by onFocusLoss but not by onFocusLoss2.
function onClickButton() {
var modal = document.getElementById('modal');
modal.style.visibility = 'visible';
modal.focus();
}
function onFocusLoss() {
var modal = document.getElementById('modal');
setTimeout(function() {
var activeEl = document.activeElement;
if (modal !== activeEl && !modal.contains(activeEl)) {
modal.style.visibility = 'hidden';
}
}, 0);
}
function onFocusLoss2() {
var modal = document.getElementById('modal');
var activeEl = document.activeElement;
if (modal !== activeEl && !modal.contains(activeEl)) {
modal.style.visibility = 'hidden';
}
}
#modal {
position: fixed;
visibility: hidden;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 1px solid red;
}
#modal > div {
padding: 16px;
}
<button onclick='onClickButton()'>Show Modal</button>
<div id='modal' tabindex='-1' onfocusout='onFocusLoss()'>
<div>Focus Test</div>
<div>
<input>
</div>
</div>
This is how I assume focus events are going, when the modal is focused and then I click inside input,
then first the modal loses focus, the body is the active element, and then the input element becomes the active element, and body loses focus.
Thus, the reason maybe that onFocusLoss2 is not handling the case because activeEl at that time is the body, while in onFocusLoss, the activeEl is the input.
My question is, why one approach is working and the other is not? I want a good technical reason. If your answer is that it gives enough time so that input element gains focus, I want to know how can you say that the time is enough and will always work?
My solution is based on this answer, though.
May wish to change your mind. When the modal is focused, add a click event to the element below it to close the modal.
<body>
<button onclick='onClickButton()'>Show Modal</button>
<div id='modal' tabindex='-1'>
<div>Focus Test</div>
<div>
<input>
</div>
</div>
</body>
function onClickButton() {
const modal = document.getElementById('modal');
modal.style.visibility = 'visible';
modal.focus();
document.body.addEventListener('click', ()=>{
modal.style.visiable = 'hidden'
})
}
Don't forget to adjust modal's z-index to make sure it's above the body.
Just like #RiverTwilight, I'm removing the focus need and simply adding an onClick event.
I placed a <div> inside your #modal and made #modal fill the whole screen, this way you can use different animations and other techniques to also animate your content as long as #modal doesn't have padding.
I hope you get your answer. ✌️
function onClickButton() {
var modal = document.getElementById('modal');
modal.style.visibility = 'visible';
modal.focus();
}
function onModalBGClick(e) {
var modal = document.getElementById('modal');
var activeEl = e.target;
if (activeEl === modal) {
modal.style.visibility = 'hidden';
}
}
#modal {
position: fixed;
visibility: hidden;
top: 0;
bottom: 0;
right: 0;
left: 0;
}
.modal-inner {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 1px solid red;
}
#modal > div {
padding: 16px;
}
<button onclick='onClickButton()'>Show Modal</button>
<div id='modal' onclick='onModalBGClick(event)'>
<div class="modal-inner">
<div>Focus Test</div>
<div>
<input>
</div>
</div>
</div>

trigger input file click on modal on first page load doesn't fire

Using angularJS, I have a modal that should trigger a input file in order to upload a file.
this is the function that triggers the click
function triggerUploadMethod()
{
inputFile = document.createElement('input');
inputFile.type = 'file';
inputFile.onchange = photoChosen;
inputFile.click();
}
The thing that is boring me is that on the FIRST page load, when I open the modal, the trigger is not fired. If I close the modal and open again, the trigger WORKS, and it will keep working until the next page load... What can be happening to not work on the first page load?
This only happens on Chrome. On Firefox, Edge and Internet Explorer the trigger works every time, even after a page load...
As a disclaimer I've never used Angular and since you didn't provide any of the other code, I went with vanilla JavaScript.
As far as I can tell, the error in your code is not from what you posted above. In the snippet below, I have taken code from W3Schools How to Make a Modal Box With CSS and JavaScript and then added your function to the part where it opens the modal on button click and it works fine (I'm on Chrome).
// Get the modal
var modal = document.getElementById('myModal');
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// This variable isn't defined in your code so I just assume
// it's somewhere at the top.
var inputFile;
// When the user clicks on the button, open the modal.
// Also creates your input and clicks it.
btn.onclick = function() {
modal.style.display = "block";
triggerUploadMethod();
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
// Create the input element and click it.
function triggerUploadMethod() {
inputFile = document.createElement('input');
inputFile.type = 'file';
// I have no idea what this is so I can't include it.
//inputFile.onchange = photoChosen;
inputFile.click();
}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content/Box */
.modal-content {
background-color: #fefefe;
margin: 15% auto; /* 15% from the top and centered */
padding: 20px;
border: 1px solid #888;
width: 80%; /* Could be more or less, depending on screen size */
}
/* The Close Button */
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
<!-- Trigger/Open The Modal -->
<button id="myBtn">Open Modal</button>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..</p>
</div>
</div>

Closing div when clicking outside of div not working on iPhone. Works fine on Mac/PC and Android

Here is the div(s). Depending on what button is clicked, one of them will appear on the screen.
var box;
var value;
var wrapper = $('.wrapper');
$('body').on('click', '#login, #register', function() {
if ($(this).attr('class')) {
value = $(this).attr('class')
} else {
value = $(this).attr('id')
}
switch (value) {
case 'login':
box = $('.loginBox');
break;
case 'register':
box = $('.registerBox');
break;
}
box.closest(wrapper).toggleClass('open');
$('input:text', box).first().focus();
});
// this successfully closes the div when I click outside of it (on Mac/PC & Android, however it does not close the div on iOS)
$('body').on('click', '.wrapper', function() {
box.closest(wrapper).toggleClass('open');
});
$('body').on('click', '.wrapper div', function(e) {
e.stopPropagation();
});
.wrapper {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
background: rgba(0, 0, 0, 0.1);
display: none;
z-index: 300;
}
.open {
display: block;
}
.blackBox {
position: absolute;
left: 50%;
top: 41%;
height: 340px;
width: 500px;
z-index: 997;
margin: 0 auto;
transform: translate(-50%, -50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="blackBox">
<div class="loginBox">
...
</div>
</div>
</div>
<div class="wrapper">
<div class="blackBox">
<div class="registerBox">
...
</div>
</div>
</div>
The 2nd function, (the toggle when clicking outside the div) successfully closes the div when I click outside of it (on Mac/PC & Android, however it does not close the div on iOS)
Is there another method I can perform for iOS?:
$('body').on('click', '.wrapper', function(){
if (/iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
// another method
}
box.closest(wrapper).toggleClass('open');
});
iStuff will only acknowledge a click event if the element is clickable. One of the conditions to make it clickable is to give it
cursor:pointer;
If that's not an option, you could use tap:
$(containerSelector).on('click tap', targetSelector, function(event) {
// have you finished that webpage already?
})
Yet another option is to use touchstart. But I personally think that's a mistake. touchstart is triggered whenever a touch event is started, whether it's a swipe, a multi-touch zoom or whatever other fancy gestures your device might recognize.
Most times, when you want to swipe, pan, zoom, you don't want click functionality to trigger. tap is the most click-like event in the world of touch gestures.
In the particular case of a dropdown, you don't want it closing on gestures aimed at better positioning it on the screen or zooming in on the area in which it opened.

Categories

Resources