2014-01-24 8 views
6

Ich habe ein HTML-Dokument, das 3 iFrames enthält, die vorherige, aktuelle und nächste Seiten darstellen. Ich versuche Seitenwischen zu ermöglichen (über das jquery touchswipe plugin), lasse aber auch Klicks auf das Dokument im iframe durchgehen. Hier ist der HTML:Über einen iFrame wischen, Klickereignisse übergeben und elementFromPoint null im Imagemap-Bereich zurückgeben

<body> 
    <div id="pages-wrapper"> 
     <div id="page1" class="page-div previous-page"> 
      <iframe id="frame1" class="page-frame"></iframe> 
     </div> 
     <div id="page2" class="page-div active-page"> 
      <iframe id="frame2" class="page-frame"></iframe> 
     </div> 
     <div id="page3" class="page-div next-page"> 
      <iframe id="frame3" class="page-frame"></iframe> 
     </div>      
    </div> 
</body> 

Wenn die Seiten-Wrapper-Element wird geklaut, entweder die vorherige oder nächste Seite wird die Aktiv-Seite. Seiten haben eine Größe von 100% und die aktive Seite füllt das Ansichtsfenster des Browsers. Alles ist in derselben Domäne. Die Dokumente des iframes können Bilder mit Imagemaps enthalten.

Leider fangen die iFrames die Mausereignisse ein und deaktivieren die Swipe-Funktion auf den übergeordneten Seiten. Wie andere vorgeschlagen haben, besteht die Antwort darin, ein transparentes div zu überlagern, mithilfe von elementFromPoint das Ziel im Dokument des iframes zu lokalisieren und ein click-Ereignis manuell an das Ziel zu senden.

Ich habe dies die coverIframes plugin mit implementiert:

$.fn.coverIframes = function(){ 
    $.each($("iframe",this),function(i,v){ 
     var ifr = $(v); 
     var wr = $("<div id='wr"+new Date().getTime()+i+"' style='z-index: 999999; opacity: 0; position:absolute; width:100%;'></div>"); 
     ifr.before(wr); 
     wr.height(ifr.height()); 
     wr.click(function(event){ 
      var iframe = ifr.get(0); 
      var iframeDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document; 
      // Find click position (coordinates) 
      var x = event.offsetX; 
      var y = event.offsetY; 
      // Trigger click inside iframe 
      var link = iframeDoc.elementFromPoint(x, y); 
      var newEvent = iframeDoc.createEvent('HTMLEvents'); 
      newEvent.initEvent('click', true, true); 
      link.dispatchEvent(newEvent); 
     }); 
    }) 
}; 

Obwohl dieser Ansatz für die meisten Elemente funktioniert, ist es nicht tun, so für eines der Gebiete imagemap - zumindest innerhalb des Chrome-Browser (Version 32). In diesen Fällen wird null zurückgegeben. Bei dem Versuch, eine Abhilfe zu finden, hier sind 3 questons in den Sinn kam:

  1. eine Möglichkeit, ein Klick-Ereignis in der übergeordneten direkt an den iframe Fenster Gibt es zu passieren und lassen Sie es das Ereignis genau behandeln, als ob der Benutzer hatte auf das Fenster geklickt? (Das heißt, das Fenster findet das Ziel, und sprudelt das Ereignis oben durch die Elemente der dom.)

  2. Gibt es eine alternative Funktion ähnlich elementFromPoint dass zuverlässig das Zielelement kehrt?

  3. Wenn ich will, um manuell das Nullergebnis auf einer Fläche behandeln, ist es ein Javascript-Funktion oder jQuery-Plugin bestehende, die bestimmen, ob ein gegebener Punkt innerhalb einer Karte des Gebiets ist? (Ich habe für eine Suche nach einem Punkt in einem Polygon einige Funktionen zu sehen.)

Dank für irgendwelche Erkenntnisse, die Sie anbieten können!

Antwort

1

Ich werde Ihnen nicht sagen, wie transparente Overlays und Ereigniserfassung zu verwenden. Ich habe das getan, und es kann funktionieren, aber es ist es nicht wert.

Aber keine Sorge, die gute Nachricht ist: Wir haben AJAX!

Verwenden Sie nicht iframe für dieses; Sie können problemlos alle Probleme mit mehreren Fensterobjekten beseitigen. Wenn sich alle Seiten auf der gleichen Domain befinden, wie Sie es gesagt haben, verwenden Sie $.ajax({url:'XXX.html'}), um den Inhalt zu erhalten und laden Sie ihn stattdessen in <div id='page1'></div>.

Wie in diesem Beispiel: https://jsfiddle.net/q69d0L63/

Gedanken:

1) angeforderten Seiten müßten wahrscheinlich einen CORS-Header, wenn sie nicht in derselben Domäne sind (aber Sie sagten gleiche Domäne, also kein Problemo).

2) Der Inhalt der angeforderten URL muss kein vollständiges HTML-Dokument sein, sondern kann nur ein HTML-Dokumentfragment sein.

Beispielcode (funktioniert auf nicht SO aufgrund Header, sondern arbeitet auf JSFiddle Um zu überprüfen, die JS-Konsole und den Netzwerkverkehr zu überwachen, während Sie klicken.):

var urls = ['page1.html', 'page2.html', 'page3.html']; // just an example; test data 
 
var curIdx = -1; 
 
swipe = function(e) { 
 
    getNextPage(); 
 
} 
 
getNextPage = function() { 
 
    curIdx = (curIdx + 1) % 3; 
 
    var url = urls[curIdx]; 
 
    $("#page_content").html('Loading...'); 
 
    $.ajax({ 
 
    url: url, 
 
    async: true, 
 
    success: function(data) { 
 
     var html = $(data).find("span:first"); // filter input if desired 
 
     $("#page_content").html(html.html()); 
 
    }, 
 
    error: function(jqXHR, status, error) { 
 
     $("#page_content").html([status, error].join(': ')); 
 
    } 
 
    }); 
 
} 
 
getNextPage();
#page_content { 
 
    background-color: #eee; 
 
    padding: 10px; 
 
    font-family: 'Segoe UI', Arial; 
 
    font-size: 20px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<input type='button' value='Touch or click to simulate swipe' onclick='swipe();' /> 
 

 
<h3>Content loaded by AJAX</h3> 
 

 
<div id='page_content'></div>