bxslider-4 icon indicating copy to clipboard operation
bxslider-4 copied to clipboard

Links in sliders aren't working - Error in the latest version of Chrome (73.0.3683.75)

Open isaiahlee opened this issue 5 years ago • 105 comments

jquery.bxslider.js -> onTouchStart -> slider.viewport.get (0) .setPointerCapture (slider.pointerId); Link (a tag) does not work due to source

isaiahlee avatar Mar 14 '19 08:03 isaiahlee

Same issue. Set touchEnabled: false for desktop clients as temp solution.

Update: check this https://github.com/stevenwanderski/bxslider-4/issues/1240#issuecomment-475947178

r10v avatar Mar 14 '19 21:03 r10v

Same issue.

haseebtirur avatar Mar 18 '19 13:03 haseebtirur

Replace this:

if (slider.settings.touchEnabled && !slider.settings.ticker) { initTouch(); }

With this:

if (navigator.maxTouchPoints > 0) { initTouch(); }

This should detect if the device viewing the slideshow has a touch screen before loading support for touch.

Note: setting touchEnabled to false didn't work for me and it also turns off all touch support.

ghost avatar Mar 18 '19 21:03 ghost

Replace this:

if (slider.settings.touchEnabled && !slider.settings.ticker) { initTouch(); }

With this:

if (navigator.maxTouchPoints > 0) { initTouch(); }

This should detect if the device viewing the slideshow has a touch screen before loading support for touch.

Note: setting touchEnabled to false didn't work for me and it also turns off all touch support.

But now you can't swipe images by mouse. It seems we have to choose now - clicking or swiping in newest Chrome. Not both 😕

MarcinSzyszka avatar Mar 22 '19 10:03 MarcinSzyszka

Accorrding to information written above, a have added to initial options of all my sliders next code:

touchEnabled : (navigator.maxTouchPoints > 0) - that enable swipe functions on mobile devices and prevent using mouse swipe for desctop browser

itimurcom avatar Mar 24 '19 10:03 itimurcom

Accorrding to information written above, a have added to initial options of all my sliders next code:

touchEnabled : (navigator.maxTouchPoints > 0) - that enable swipe functions on mobile devices and prevent using mouse swipe for desctop browser

Still can't click on chrome mobile...

glo-www avatar Mar 26 '19 09:03 glo-www

Same here with Chrome 73.0.3683.86 (Official Build) (64 bits)

cedricbdev avatar Mar 26 '19 09:03 cedricbdev

Same here. touchEnabled: false seems to fix this on desktop though.

larsschwarz avatar Mar 26 '19 11:03 larsschwarz

Getting the following 'Violation' from the console...

[Violation] Added non-passive event listener to a scroll-blocking 'touchmove' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952

But if you try adding { passive: true } , like the message suggests, to any of the touch events the links will work but it'll break the slider since all of the functions used in touch events use preventDefault().

For more info

minusthebear02 avatar Mar 26 '19 17:03 minusthebear02

I have created a code pen with a link in the first slider that shows this problem (link can't be clicked in latest Chrome):

https://codepen.io/smohadjer/pen/VROdJE

smohadjer avatar Mar 27 '19 07:03 smohadjer

Accorrding to information written above, a have added to initial options of all my sliders next code:

touchEnabled : (navigator.maxTouchPoints > 0) - that enable swipe functions on mobile devices and prevent using mouse swipe for desctop browser

Adding this disables touch support in iPhone too!

smohadjer avatar Mar 27 '19 08:03 smohadjer

What I have found is that if you put the link as a first child inside the slide and you have only one link there, then it works just fine with the original setting. Sometimes you have to click twice but both on desktop and phone the link works in the latest Chrome - see http://newhow.archi/ :-)

vsindylek avatar Mar 27 '19 08:03 vsindylek

@vsindylek That's not going to help me, we have dynamic content inside slides coming from CMS.

smohadjer avatar Mar 27 '19 08:03 smohadjer

The problem in Chrome seems to be related to use of setPointerCapture() in bxslider. When I comment out the following snippet in jquery.bxslider.js links start working in Chrome and touch capabilities are also preserved both on desktop and mobile.

if (slider.viewport.get(0).setPointerCapture) {
	slider.pointerId = orig.pointerId;
	slider.viewport.get(0).setPointerCapture(slider.pointerId);
}

But this is not a perfect solution since if you drag slides with mouse on desktop Chrome and your mouse moves outside slider boundary you may end up seeing parts of two slides at the same time.

smohadjer avatar Mar 27 '19 08:03 smohadjer

Replace this:

if (slider.settings.touchEnabled && !slider.settings.ticker) { initTouch(); }

With this:

if (navigator.maxTouchPoints > 0) { initTouch(); }

This should detect if the device viewing the slideshow has a touch screen before loading support for touch.

Note: setting touchEnabled to false didn't work for me and it also turns off all touch support.

For me this seems to fix the issue. Checkout thefastpark.com

haseebtirur avatar Mar 27 '19 08:03 haseebtirur

@haseebtirur Be careful with that, you will loose touch functionality on iPhone since Safari doesn't support maxTouchPoints. See browser support for it here: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/maxTouchPoints

smohadjer avatar Mar 27 '19 08:03 smohadjer

I might have found a reliable fix for this. The problem happens in Chrome because it doesn't fire a click event after pointerup unlike other browsers such as Firefox. This is because bxslider in onTouchStart function sets slider viewport as target of all succeeding pointer events. Now if you have a link inside a slide when you click the link the target of pointerdown is not slider viewport, but the link content and since this target is different from pointerup target (which is slider viewport), then Chrome doesn't fire a click. The solution is to make sure pointerup fires on the same element as pointerdown so that Chrome fires a click. So we need to refactor this snippet:

        if (slider.viewport.get(0).setPointerCapture) {
          slider.pointerId = orig.pointerId;
          slider.viewport.get(0).setPointerCapture(slider.pointerId);
        }

to this:

        if (e.target.setPointerCapture) {
          slider.pointerId = orig.pointerId;
          e.target.setPointerCapture(slider.pointerId);
        }

This solved the problem for me in Chrome without loss of any functionality in any browser or mobile device.

smohadjer avatar Mar 27 '19 10:03 smohadjer

I might have found a reliable fix for this. The problem happens in Chrome because it doesn't fire a click event after pointerup unlike other browsers such as Firefox. This is because bxslider in onTouchStart function sets slider viewport as target of all succeeding pointer events. Now if you have a link inside a slide when you click the link the target of pointerdown is not slider viewport, but the link content and since this target is different from pointerup target (which is slider viewport), then Chrome doesn't fire a click. The solution is to make sure pointerup fires on the same element as pointerdown so that Chrome fires a click. So we need to refactor this snippet:

        if (slider.viewport.get(0).setPointerCapture) {
          slider.pointerId = orig.pointerId;
          slider.viewport.get(0).setPointerCapture(slider.pointerId);
        }

to this:

        if (e.target.setPointerCapture) {
          slider.pointerId = orig.pointerId;
          e.target.setPointerCapture(slider.pointerId);
        }

This solved the problem for me in Chrome without loss of any functionality in any browser or mobile device.

I tried this solution and tested on mobile (iphone X with chrome) and I cannot slide left or right. On Desktop, when I slide right or left, the click event is fired automatically.

lorguzman avatar Mar 27 '19 14:03 lorguzman

@lorguzman I just installed Google Chrome on iOS 12.1.2 and sliding works, but I have noticed issues in Edge/IE11, so this solution is still not good enough.

smohadjer avatar Mar 27 '19 14:03 smohadjer

Just tested this on Chrome 74.0.3729.28 with the patch applied from above. Mobile is draggable now but links are fired as soon as you attempt to drag on desktop.

Pross avatar Mar 27 '19 15:03 Pross

@smohadjer 's possible solution above didn't cover all the bases for me. Links were not clickable in Safari on iPhone X, iPad Pro, iPad Air... so on. Tested in BrowserStack. Although I appreciate his work so thank you for that suggestion.

Outside of doing a bunch of conditional checking for user agents which still isn't super reliable or checking for like modernizr.touch which also isn't great. I have decided to just disable touch for right now and try to buy some time to keep poking at this or hopefully someone smarter than me finds the solution.

SpatialAnomaly avatar Mar 27 '19 16:03 SpatialAnomaly

@SpatialAnomaly I wouldn't rely on BrowserStack, I tested on actual devices (both iOS and Android phones) and links worked there, but as I said IE11/Edge have problem with this, so we need a better solution. For now I'm going to use my very first suggestion and simply comment out the line with setPointerCapture(). Did you try that or have any problem with it?

https://github.com/stevenwanderski/bxslider-4/issues/1240#issuecomment-477028547

smohadjer avatar Mar 27 '19 16:03 smohadjer

Hi Guys,

Here is the workaround I found:

First of all you need to move the "slider.hasMove = true;" to different location, so your code in the onTouchMove function needs to be something like this:

  // Remove this as we don't want to mark it a movement if it's not within the minimum range
  //slider.hasMove = true;

  // x axis swipe
  if ((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX) {
    e.preventDefault();
    slider.hasMove = true;
  // y axis swipe
  } else if ((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY) {
    e.preventDefault();
    slider.hasMove = true;
  }

And now the code is already there for the click to work just for some reason Chrome doesn't trigger the click element trough jQuery (didn't dig any further just for this) but it does work with the vanila click method in the onTouchEnd like this:

    try {
      slider.originalClickTarget.click();
    } catch(error) {
      $(slider.originalClickTarget).trigger({
        type: 'click',
        button: slider.originalClickButton,
        buttons: slider.originalClickButtons
      });
    }

I used try and catch as they say this click method is not that supported on android so in that case we fall back to the original jquery method.

I tested this on Chrome, Firefox, Android and seems to be working just fine without breaking anything.

Regards, Julius

pijulius avatar Mar 28 '19 17:03 pijulius

Tried the fix as suggested Julius and now swiping on firefox desktop opens the link on swipe.

Pross avatar Mar 28 '19 17:03 Pross

I know it's not a good solution, but BxSlider 4.2.1 works fine with the latest version of Chrome as far as I tested.

keiichi-takio avatar Mar 29 '19 01:03 keiichi-takio

@keiichi-takio Did you test this on any mobile platforms as well?

ghost avatar Mar 29 '19 17:03 ghost

@keiichi-takio Did you test this on any mobile platforms as well?

Actually I rolled back to v4.1.2 and it seems to be working for the most part. Not the greatest, and also not 100% sure why that would be ok versus a later version.

ghost avatar Mar 29 '19 19:03 ghost

Also had to roll back to 4.1.2. Sadly, I hope soon we will find a better solution

formatiai avatar Mar 30 '19 08:03 formatiai

In some cases, for example, when using a system like Wordpress or any plugin that does not have direct access to its code, the following code can be added as a temporary solution. The code takes the address from the link and directs it directly parallel to the problem resulting from the touch event.

(function($){
  $(document).ready(function(){
	if(navigator.maxTouchPoints === 0) {
            $('.bx-viewport a').on("mousedown", function(e){
                var linkUrl = $(this).prop('href');
                window.location.href = linkUrl;
            });
        }
  });
})(jQuery);

Mosharush avatar Mar 31 '19 19:03 Mosharush

Tried every suggestion here. iOS still not working :(

ESTUDIOCRU avatar Apr 01 '19 14:04 ESTUDIOCRU