Disable callout (context menu) on mobile IE - javascript

In a web app, I need to disable the default callout that mobile browsers shows when touching and holding ("long tap") on a touch target, such as an <img> or a link.
I am already using -webkit-touch-callout: none for iPhone and iPad. I tried -ms-touch-action:none and touch-action:none for IE, but this doesn't seem to work (tested on IE11, Windows Phone 8).
This post from the W3 mailing list suggests adding a listener for the "contextmenu" event in Javascript and calling e.preventDefault(). This does not seem to work either.
Any suggestions?

I did a bunch of research and as far as I can tell these are your two options:
Use a transparent <div> to cover the link/image
using a <div> with style="background: url(yourimage.png)" instead of <img src="yourimage.png">
The core problem is that mobile IE on Windows Phone doesn't properly handle preventDefault with contextmenu events. That is the proper way to do this and it works in every other browser. The contextmenu event is fired on WP IE but it actually happens when the long press context menu is dismissed. It should happen before even showing the menu so that you can prevent it.
Here are some of the other options I tried:
Events: I tried registering for every event and using e.preventDefault(), e.stopPropagation() and return false to prevent all of the default actions. JSBin example.
Use element:before or element:after to place an element on top of the link or image. I thought this might be able to automatically do what the transparent <div> does. Unfortunately the :before or :after content is part of the <a> so it is all clickable as well. Also, apprently <img> elements don't support :before or :after. JSBin example.
user-select: none
-ms-touch-action
-webkit-touch-callout: none
I even pinged someone on the IE team and he didn't know of a way.

I tried every "normal" or "elegant" option out there, but apparently IE11 mobile ignores every single one of them.
CSS properties: -webkit-touch-callout equivalent for IE
The preventDefault method Microsoft suggests: https://msdn.microsoft.com/en-US/en-en/library/jj583807(v=vs.85).aspx
Catching all touch events: Disabling the context menu on long taps on Android
A homebrewn oncontextmenu callback with stopPropagation and preventDefault
The only thing actually working is the old ugly div-over-image:
<div class="img-container">
<img src="path/to/image.jpeg" />
<div class="cover"></div>
</div>
CSS:
.img-container {
position: relative;
}
.cover {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}

Related

behavior:smooth param breaks window.scroll in keyboard event in chrome

I am pulling my hair out because for some reason when I pass behavior: smooth as a parameter to window.scroll, the function stops working altogether in Chrome. Without behavior:smooth it scrolls as expected. I'm pretty sure this is a Chrome bug, but I've used behavior:smooth elsewhere without issue, so I'm wondering what's special about the config on this page which is causing the problem. Here's the set-up, which will hopefully allow you to reproduce:
I have a document with several viewport-sized divs like so:
html:
<body>
<div class="slide" data-ind="0"></div>
<div class="slide" data-ind="1"></div>
<div class="slide" data-ind="2"></div>
</body>
css:
.slide{
width:100%;
height:100vh;
border-bottom:1px solid black;
box-sizing:border-box;
}
I'm trying to use an event listener to scroll to a slide when you press an arrow key, like so:
window.addEventListener('keydown',function(){
if(event.key=='ArrowRight'){
let el=document.querySelector('.slide[data-ind="1"]');
let dist=el.offsetTop;
window.scroll({
top:dist,
left:0,
behavior:'smooth'
})
}
})
Update: Some more testing has made it clear that the bug only happens when window.scroll is used within a keyboard event.
I was able to resolve this by adding event.preventDefault(); to the keyboard event. Still unclear if this is intended/standard behavior, as Firefox had no such issue even without adding this line.

Input element click on mobile device browser behaves differently than in Chrome device rendering

I have a hard to debug issue where a click on an input element behaves completely different on my Samsung S10 than in my desktop Chrome browser (also when using device testing tools).
Here's how to test:
on a small mobile design (max-width: 56em) a blue filter bar appears at the bottom of the screen
Click it to show all filters, a popup menu appears (you can go back to results by clicking button "Bekijk resultaten")
Click "+ Specificeer" at the bottom of that screen
In the small range specification popup that appears click the first input element (placeholder="van")
In Chrome on desktop the user can now enter a number. Also when I use Chrome device debugging tools and set it to iPhoneX, Galaxy S5, Galaxy Fold rendering etcetera it works just fine.
But when I load my live site on my Galaxy S10 in the Chrome browser, the moment the user clicks the input element to enter a number, the rest of the filter popup menu is hidden, and it only shows part of the range specification popup. Scrolling of the page is completely disabled. I'm thinking that certain events are handled differently, but I can't figure out which ones and why.
I tried monitoring events using monitorEvents(window,"click");, but no click events show
Logged events via Performance tab, but could not find the culprit
I have no idea why anymore and I can't reproduce it in Chrome desktop browser to actually debug it.
UPDATE 1
The issue was the mobile virtual keyboard that trigger the resize method.
Fixed it by checking for width change:
var initialWidth = $(window).width(), initialHeight = $(window).height();
window.addEventListener('resize', function () {
if ($(window).width() != initialWidth) {//the width was changed
}
})
Well, I've played around. illusion is totally right.
I've copied some styles from .filters .mobile class to .filters_TEST
.filters_TEST{
&.active{
height: auto;
flex-grow:1;
overflow: auto;
opacity: 1;
z-index: 100;
padding: 0;
background-color: #FFF!important;
min-height: 100vh;
.modal_container{
background-color: #fff;
overflow: auto;
overflow-x: hidden;
position: relative;
width: 100%;
height: 100vh;
overflow-y: hidden;
#mobilefilters{
display:block;
}
}
}
}
added test button:
<span class="js-callmodal display-mobile-only">CALL MODAL</span>
and on button click added new class to .
$('.js-callmodal').on('click',function(){
$('.filters_TEST').addClass('active');
});
now when you click:
CALL MODAL -> Specificeer -> input
modal stays in place;
to truly fix your problem you should search what removes .mobile class when input is triggered.
I guess the code should be somewhere in file: _genfuncs.min.js?v=90
While debugging, I found that when the input is in focus and the keyboard pops up, that instant .mobile class is removed from section.filters. You'll have to see for any event handler that removes the .mobile class on any event. Secondly, after the bug was encountered I again added the removed .mobile class manually to section.filters and the modal was back in place working properly. After clicking "Specificeer" it gives rise to another bug, where the main page becomes unscrollable. Also at the same instant there is another error TypeError which could possibly be the cause of the other bug...

Change image attr src not working on safari? [duplicate]

When I use jQuery for a simple click event it only works for links. Is there a way to make it work for spans etc:
$("span.clicked").live("click", function(e){alert("span clicked!")});
$("a.clicked").live("click", function(e){alert("link clicked!")});
The SPAN works in Safari but not Mobile Safari (on iPhone or iPad) whereas the A tag works in both.
I struggled with this as well. After lots of toying around and trying to figure out the problem, I came across a simple solution.
If you set the element's cursor to pointer, it magically works again with Jquery's live and the click event. This can just be set globally in the CSS.
You need to listen for the "touchstart" and "touchend" events. Add the listeners with jQuery...
$('span').bind( "touchstart", function(e){alert('Span Clicked!')} );
You may wish to listen for a touchstart and touchend so that you can verify that the element targeted when the finger touched is the same as the element targeted when the finger was removed.
I'm sure there is probably a better way to do it but that should work :)
Edit: There is a better way! See https://stackoverflow.com/a/4910962/16940
You actually don't need to use the touchstart or touchend event, so long as the 'span' tag (or anything other than an 'a' tag) has a css property of:
cursor:pointer
the click will register
You can also coax the browser to generate click events by adding an empty onclick attribute. For a belt-and-braces approach in case either approach stops working in any given iOS update, you could use something like this:
$("span.clicked").live("click", function(e){alert("span clicked!")})
.attr('onclick','')
.css('cursor','pointer');
(assuming you don't have any actual onclick attributes you don't mind obliterating)
You can add an empty onclick attribute, like so:
<span onclick=''>Touch or Click Me</span>
jQuery('span').live('click', function() { alert('foo'); });
I tried everything and none of the tricks worked. It turned out I couldn't get click events because I had a video element under my img. video elements apparently eat click events.
When targeting iOS you have to take the following into consideration: doing event delegation in jQuery like $(document).on('click', '.target-element', function (event) {...}); will not work. You have to add either onclick="" to the target HTML element or cursor: pointer to its styles.
Taken and adapted from http://gravitydept.com/blog/js-click-event-bubbling-on-ios:
It turns out that Safari on the iPhone does not support event delegation for click events, unless the click takes place on a link or input. Fortunately there are workarounds available.
That's the reason while the <a> tag works while <span> doesn't.
My approach to solve this misunderstanding on document.click.
Add into html after tag body next tag
<body>
<div id="overlaySection" onclick="void(0)"></div>
...
</body>
Some style for that tag
`#overlaySection {
position: fixed;
top: 0;
left: 0;
z-index: 1;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0);
cursor: pointer;
visibility: hidden;
opacity: 0;
content: "";
}
#overlaySection.active {
opacity: 1;
visibility: visible;
}`
Some JQuery staff
// hide overlay on document click
$('#overlaySection').click(function(){
$(this).removeClass('active');
});
and the main thing to active this overlay
$('.dropdown > span').click(function() {
...
$('#overlaySection').addClass('active');
...
});
Hope this approach will be useful to someone. Happy coding!

jQuery Selectric bug on iPad

I use jQuery Selectric plugin for customize select's.
$('select').selectric({
disableOnMobile: false
});
If i open select on iPad device my left column move up
.left-column {
position: fixed;
left: 0;
top: 0;
width: 200px;
height: 100vh;
background: #F00;
z-index: 100;
}
Please, help with it. Demo here: http://output.jsbin.com/seleyi
UPD: test at browserstack iOS < 7 - no problem, iOS 8.3 - have some problem, iOS 9.1 have this bug
It's bug iOS 9, include in iOS 8, but in 9 version include partly.
Bug with input, with attribute readonly="readonly". Selectric use hide input:
What happen:
If click on selectric-wrapper start method _open.
Method _open set focus on hide input.selectric-input. It make selectric plugin and i don't know why. May be, more simple add listeners for keystrokes on a hidden element. And handle such events when an item has focus. Why input? If you use another element, then pressing the arrow keys, we will also scroll the document itself. Because, use input , although I could be wrong. Maybe better input for e-readers, ie, used it to enhance accessibility.
And when focus comes to input , despite the fact that it is readonly, iOS (I think so) tries to allocate space for the keyboard. I can advise a simple workaround:
$(".selectric-input[readonly]").on("focus", function(evt) {
this.blur();
});
Ie when the focus input immediately rid of him, because on iPads impossible to move through the list using the keyboard, the functionality should not be compromised.

javascript : toggle scrolling only on document body

I need a toggle function for a dialog popup that locks page scroll, but permits the dialog to be scrollable.
I have tried CSS only with, but the code does not work in Safari iOS.
body{overflow:hidden; } //does not work in Safari iOS
So, i think I may need to use some JS magic for this to work. Any Ideas? thx.
You can toggle a class on the body to stop the scrolling: http://codepen.io/J_Mack/pen/zGMGyM
.stop-scrolling {
width: 100vw;/*can also use %*/
height: 100vh;/*can also use %*/
overflow: hidden;
}
Read before you use vw/vh: http://caniuse.com/#feat=viewport-units

Categories

Resources