Why is there an iframe in swiper? In fact, when I encountered this requirement, I did not expect to have such a lazy operation, swiper embedded sites, each swipe to switch between one site? Think about what sounds cool, but not what you do. When you happily drop iframe into each swiper-slide, the page doesn’t slide, you cry, you despair. If you go to Google and search for solutions, you’ll find that the authors of these libraries are more desperate than you:


“This is the iframe pot, I can’t listen for events in the iframe.”








The simplest way is :pointer-events

Pointers-events is a new property in CSS3, which makes it impossible for the element to listen to any events. If you set this property to iframe, you can switch between sites. However, the downside of this approach is that, as the official introduction states, the entire element can’t listen for events, making all interactions within the site inoperable unless you have a purely presentational static site. So, if you want to use this method to solve the problem of not sliding, first make sure that your site is purely static without any events that need to be triggered.

Listen for sliding events within an IFrame

This method is suitable for both internal and external urls in the same domain, because we need to listen for events in the iframe directly on the parent page:

// A variable used to calculate the sliding directionlet startX,startY,endX,endY,distanceX,distanceY; 
let iframe = document.querySelector('iframe');
const MOVE_RATE = 2;
iframe.contentWindow.addEventListener('touchstart'.function (e) {
    startX = e.targetTouches[0].pageX;
    startY = e.targetTouches[0].pageY;
});
iframe.contentWindow.addEventListener('touchmove'.function (e) {
    endX = e.targetTouches[0].pageX;
    endY = e.targetTouches[0].pageY;
    distanceX = endX - startX;
    distanceY = endY - startY;
    if(math.abs (distanceX) > math.abs (distanceY) && distanceX > (body.clientWidth/MOVE_RATE)){//slideNext and SlidePrev)() are all API for swiper myswiper.slidenext ()}else if(Math.abs(distanceX) > Math.abs(distanceY) && distanceX < (body.clientWidth/MOVE_RATE)){
        myswiper.slidePrev()
    }else{
        console.log('Click not to slide'); }});Copy the code

The idea of this scheme is to obtain the window inside the iframe first, and then listen to the TouchStart and Touchmove events of the window. According to the sliding direction and distance, judge whether the window is sliding left or right, and call the API of swiper sliding forward or backward. If you have studied iframe embedding in swiper, you must have seen this solution. However, this solution has two drawbacks: First, when swiper has more than 3 pages, the touchMove event is triggered multiple times, resulting in multiple calls to the slideNext or slidePrev method. The user gently slides the page and slides to the last page directly. The second problem is that it cannot handle cross-domain urls. In fact, some requirements need to embed some partner urls, and these urls are not necessarily in the same domain. My solution to the first case is to declare two variables as counters for left and right slides, make the TouchMove event execute only once, and empty the counter when a slide is complete to ensure the next slide in the same direction:

letleft_slide_count = 0, right_slide_count = 0; const COUNT_LIMIT = 2; . .if(math.abs (distanceX) > math.abs (distanceY) && distanceX > (body.clientWidth/MOVE_RATE)){//slideNext and SlidePrev)() are all API for swiper left_slide_count ++;if( left_slide_count < COUNT_LIMIT ){
       myswiper.slideNext()
   }
}else if(Math.abs(distanceX) > Math.abs(distanceY) && distanceX < (body.clientWidth/MOVE_RATE)){
   right_slide_count ++;
   if( right_slide_count < COUNT_LIMIT ){
       myswiper.slidePrev()
   }
}else{
   console.log('Click not to slide');
}
Copy the code

We also need to add some configuration to swiper:

letswiper = new Swiepr({ ... . On: {/ / when the end of the slide, empty counter slideChangeTransitionEnd:function(){ left_slide_count = 0; right_slide_count = 0; }}})Copy the code

The second problem can be solved with postMessage.

Use postMessage to resolve sliding to embed cross-domain websites

Swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr: swiepr

letleft_slide_count = 0, right_slide_count = 0; const COUNT_LIMIT = 2; . .if(math.abs (distanceX) > math.abs (distanceY) && distanceX > (body.clientWidth/MOVE_RATE)){//slideNext and SlidePrev)() are all API for swiper left_slide_count ++;if( left_slide_count < COUNT_LIMIT ){
       window.parent.postMessage("right-move"."*")}}else if(Math.abs(distanceX) > Math.abs(distanceY) && distanceX < (body.clientWidth/MOVE_RATE)){
   right_slide_count ++;
   if( right_slide_count < COUNT_LIMIT ){
       window.parent.postMessage("left-move"."*")}}else{
   console.log('Click not to slide');
}

Copy the code

Parent pages need to listen for postMessage events:

window.postMessage("message".function(e){
    if(e.data == "right-move") {if( left_slide_count < COUNT_LIMIT ){
         myswiper.slideNext()
       }
    }else if(e.data == "left-move") {if( right_slide_count < COUNT_LIMIT ){
         myswiper.slidePrev()
       }
    }
})
Copy the code

Of course, this method also does counter processing. There are also two drawbacks to this method. The first is that when you swipe the screen, it works fine, but if you keep your hand on the screen, the screen reaches a certain threshold and you switch between the two pages until you let go. The second disadvantage is that it needs to embed a JS script in the embedded website. If you want to embed a pure third party website such as Taobao, then this method will not work. Is there a way to directly embed the third party website and support sliding? I’m sorry that I didn’t find it, but I found a library called iframeTracker when I was turning over the issue, which can listen to the click events in iframe (of course, this is simulated, in fact, it can’t be monitored). Although it is a jquery library, but the internal source is very simple, can be easily converted into JS, do PC friends at the same time need to listen to iframe click events can see this library, I also briefly introduced here the implementation of this library: On the PC, we can listen for the mouseover and mouseout events of the iframe. Then, we can write an input form outside the page. When we hover over the iframe, we can have the input form execute the focus event. The blur event for the input is triggered, and the blur event for the window is also triggered. In this case, we listen for the blur event for the window, even if we catch the click event for the iframe. As for monitoring mobile terminal touch events, friends have a good idea?