iPhone Safari Web App เปิดลิงก์ในหน้าต่างใหม่


155

ฉันมีปัญหากับเว็บหลังจากเพิ่มไอคอนไปที่หน้าจอหลัก หากเว็บเปิดใช้งานจากหน้าจอหลักลิงก์ทั้งหมดจะเปิดในหน้าต่างใหม่ใน Safari (และฟังก์ชันการทำงานเต็มหน้าจอจะหายไป) ฉันจะป้องกันได้อย่างไร ฉันไม่พบความช่วยเหลือใด ๆ มีเพียงคำถามเดียวที่ยังไม่ได้ตอบ


3
ตอนนี้คุณสามารถใช้พารามิเตอร์ในscope manifest.jsonดูคำตอบของฉันสำหรับรายละเอียดเพิ่มเติม ฉันทดสอบใน iOS 11.3 แล้วและใช้งานได้
Amir Raminfar

3
หากต้องการย้ำสำหรับทุกคนที่กำลังดิ้นรนกับ iOS 11.3 ที่เปิด Safari โปรดดูคำตอบของ @ AmirRaminfar ที่นี่: stackoverflow.com/a/49604315/32055
Chris Haines

คำตอบ:


110

ฉันพบโซลูชัน JavaScript ในกรอบงานiWebKit :

var a=document.getElementsByTagName("a");
for(var i=0;i<a.length;i++)
{
    a[i].onclick=function()
    {
        window.location=this.getAttribute("href");
        return false
    }
}

25
ในการระบุสิ่งที่ชัดเจนและทำให้ชัดเจน: iOS ให้การเชื่อมโยงใน Web Apps เป็นสิ่งที่ควรเปิดใน Safari และการเปลี่ยนแปลงตำแหน่งจาวาสคริปต์เป็นการกระทำในแอปที่อนุญาตให้ saty ในเว็บแอป โค้ดด้านบนใช้งานได้เพราะป้องกันการเชื่อมโยงเริ่มต้นแทนที่ด้วยการโทร js nav
Oskar Austegard

6
มีตัวอย่างตรงกันข้ามไหม? บังคับให้แอปพลิเคชันบนเว็บของ iPhone เปิดหน้าเว็บใน Safari แม้ว่าจะเปลี่ยนสถานที่เป็นจาวาสคริปต์หรือไม่
tkahn

1
@Pavel ขอบคุณสำหรับการกล่าวถึง iwebkit :) ช่วยในการรับปริมาณข้อมูล: D
cmplieger

3
[].forEach.call(document.links, function(link) { link.addEventListener("click", function(event) { event.preventDefault(); window.location = this.href; }) });
alex

1
สิ่งนี้มีผลข้างเคียงหรือไม่?
pingu

94

โซลูชันอื่น ๆ ที่นี่ไม่ได้คำนึงถึงลิงก์ภายนอก (ซึ่งคุณอาจต้องการเปิดภายนอกใน Safari) หรือไม่บัญชีสำหรับลิงก์ที่เกี่ยวข้อง (โดยไม่มีโดเมนอยู่ในนั้น)

โครงการ html5 mobile-boilerplate เชื่อมโยงกับส่วนสำคัญนี้ซึ่งมีการอภิปรายที่ดีในหัวข้อ: https://gist.github.com/1042026

นี่คือรหัสสุดท้ายที่มากับ:

<script>(function(a,b,c){if(c in b&&b[c]){var d,e=a.location,f=/^(a|html)$/i;a.addEventListener("click",function(a){d=a.target;while(!f.test(d.nodeName))d=d.parentNode;"href"in d&&(d.href.indexOf("http")||~d.href.indexOf(e.host))&&(a.preventDefault(),e.href=d.href)},!1)}})(document,window.navigator,"standalone")</script>

วิธีนี้ใช้งานได้ดียกเว้นหน้าเดียวหน้า "ติดต่อเรา" สำหรับ บริษัท ของเรา แทนที่จะแสดงหน้ามันจะเปิดแอปพลิเคชั่น "แผนที่" และระบุตำแหน่งสำนักงานของเรา สิ่งใดที่ทำให้เกิดปัญหานี้และเราจะแก้ไขได้อย่างไร
Jonathan

@ Jonathan ฉันไม่แน่ใจ จะไม่เกิดขึ้นหากคุณลบสคริปต์นี้หรือไม่ อาจโพสต์ลิงก์ไปยังเว็บไซต์ของคุณ? หรือเปิดคำถามใหม่นั่นอาจจะดีกว่า
rmarscher

@rmarscher เกิดขึ้นเฉพาะเมื่อเรียกใช้รหัสที่คุณให้และไม่ใช่ ฉันเป็นนักพัฒนาเว็บและฉันไม่เข้าใจว่าทำไมมันถึงจัดการกับลิงก์ด้วยวิธีนี้ ฉันไม่มี URL ของหน้าเพราะในขณะนี้ยังไม่ได้ใช้รหัสดังนั้นคุณจะไม่สังเกตเห็น นอกจากนี้ยังส่งผลต่อ Safari ปกติเช่นกันและไม่เพียง แต่เป็นแบบสแตนด์อโลน ขอบคุณสำหรับคำตอบ!
Jonathan

นี่ควรเป็นคำตอบที่ได้รับการยอมรับและใช้งานได้ดีกับไคลเอนต์แบบเต็มหน้าจอ iPad1 ของฉันที่สร้างด้วย PHPRunner โดยการวางรหัสในส่วนหัว ไม่แน่ใจว่าทำไมมันถึงงงงวยเพราะดูเหมือนว่ารหัสค่อนข้างสั้นที่สามารถเขียนได้อย่างชัดเจนโดยไม่มีค่าใช้จ่าย BW มาก ... นั่นเป็นเรื่องที่ค่อนข้างพิถีพิถัน
sradforth

4
สิ่งนี้จะแบ่งสิ่ง Bootstrappy เช่นลิงก์ href = "#" ที่ใช้โดยฟังก์ชั่น js
Sean

47

หากคุณใช้ jQuery คุณสามารถทำได้:

$("a").click(function (event) {
    event.preventDefault();
    window.location = $(this).attr("href");
});

1
โปรดอธิบายว่าทำไม. live () อาจดีกว่า
ajcw

8
สดจะเชื่อมโยงเหตุการณ์ไปยังลิงก์ทั้งหมดรวมถึงลิงก์ที่ยังไม่มีอยู่คลิกจะเชื่อมโยงกับลิงก์ที่มีอยู่ในปัจจุบันเท่านั้น
msaspence

ขอบคุณ! ผู้ช่วยชีวิต ฉันใช้เวลาหลายชั่วโมงเพื่อหาสาเหตุว่าทำไมซาฟารีจึงโหลดตลอดเวลา
สตีฟ

1
+1 จากฉัน - ใช้this.hrefแทนที่จะชี้ไปยังวัตถุ jQuery แต่ขอบคุณสำหรับคำตอบนี้ ทำงานบน iOS6
เฟนตัน

17
.live () ถูกเลิกใช้เมื่อ jQuery 1.7และเอาออกเป็น 1.9 ใช้ $ (เอกสาร) .on ('คลิก', 'a', ฟังก์ชัน () {... }) แทน
Tom Davies

21

สิ่งนี้ใช้ได้กับฉันใน iOS 6.1 และด้วยลิงก์ Bootstrap JS (เช่นเมนูแบบเลื่อนลงและอื่น ๆ )

$(document).ready(function(){
    if (("standalone" in window.navigator) && window.navigator.standalone) {
      // For iOS Apps
      $('a').on('click', function(e){
        e.preventDefault();
        var new_location = $(this).attr('href');
        if (new_location != undefined && new_location.substr(0, 1) != '#' && $(this).attr('data-method') == undefined){
          window.location = new_location;
        }
      });
    }
  });

1
+1 วิธีนี้จะตรวจสอบว่าคุณกำลังใช้งานเว็บแอพก่อนแก้ไขลิงก์หรือไม่
Trolley

1
ใช้งานได้กับ iOS 8.0.2! ขอบคุณ
Joel Murphy

1
@sean ฉันมี webapp อื่นที่ทำงานใน iPad ซึ่งใช้แผนที่รูปภาพเป็น href และรหัสนี้ใช้งานไม่ได้ .. มันใช้งานได้ดีสำหรับลิงก์อื่น ๆ ทั้งหมด แนวคิดใดที่จะทำให้โค้ดนี้ทำงานกับแผนที่รูปภาพได้? ฉันได้ลองคัดลอกทั้งก้อนและแทนที่$('a').on('click'ฟังก์ชั่น (e) {`ด้วย$('area').on('click', ฟังก์ชั่น (e) {` แต่นั่นก็ไม่ได้ผลเหมือนกัน ความคิดใด ๆ
nematoth

ในกรณีที่คุณมีอยู่แล้วฟังก์ชั่นการคลิกที่กำหนดไว้aด้วยhref="#"แล้วคุณสามารถจะเฉพาะเจาะจงมากขึ้นในการเลือก jQuery เช่น$('a[href!="#"]')
CJK

13

นี่เป็นคำถามเก่าและโซลูชันจำนวนมากที่ใช้ javascript ตั้งแต่นั้นมา iOS 11.3 จะวางจำหน่ายและคุณสามารถใช้สมาชิกขอบเขตได้แล้ว สมาชิกขอบเขตคือ URL เหมือน"/"ที่ทุกเส้นทางภายใต้ขอบเขตนั้นจะไม่เปิดหน้าใหม่

สมาชิกขอบเขตเป็นสตริงที่แสดงขอบเขตการนำทางของบริบทแอปพลิเคชันของเว็บแอปพลิเคชันนี้

นี่คือตัวอย่างของฉัน:

{
  "name": "Test",
  "short_name": "Test",
  "lang": "en-US",
  "start_url": "/",
  "scope": "/",
  ...
}

นอกจากนี้คุณยังสามารถอ่านเพิ่มเติมได้ที่นี่ ฉันยังแนะนำให้ใช้เครื่องกำเนิดซึ่งจะให้ฟังก์ชั่นนี้

หากคุณระบุขอบเขตทุกอย่างทำงานได้ตามที่คาดหวังเช่นเดียวกับ Android จุดหมายปลายทางที่อยู่นอกขอบเขตจะเปิดใน Safari โดยมีปุ่มย้อนกลับ (เล็ก ๆ ในแถบสถานะ) ไปยัง PWA ของคุณ


7
น่าเสียดายที่ฉันไม่เชื่อว่าคุณสามารถรวมเว็บไซต์อื่น ๆ (เช่นการเข้าสู่ระบบ OAuth ในโดเมนอื่น) ในขอบเขต
bhollis

เฮ้ @Amir ฉันสร้าง pwa โดยใช้ Angular และบน Android ฉันได้รับข้อความ 'เพิ่มไปที่หน้าจอหลัก' เนื่องจากดูเหมือนว่ามันอ่าน manfest.json ของฉันถูกต้อง อย่างไรก็ตามสำหรับ IOs Chrome / Safari ไม่มีคำแนะนำให้ ...
ustad

5

จากคำตอบของ Davids และความคิดเห็นของ Richards คุณควรทำการตรวจสอบโดเมน มิฉะนั้นลิงก์ไปยังเว็บไซต์อื่น ๆ จะเปิดขึ้นในแอปพลิเคชันเว็บของคุณด้วย

$('a').live('click', function (event)
{      
    var href = $(this).attr("href");

    if (href.indexOf(location.hostname) > -1)
    {
        event.preventDefault();
        window.location = href;
    }
});

นอกจากนี้ในการแก้ปัญหาข้างต้น ต้องการการตรวจสอบโดเมนเพื่อป้องกันไม่ให้ผู้คนเปิดเว็บไซต์ภายนอกในแอป นอกจากนี้ยังทำงานบน iOS 5
เอียน

ทำงานบน iOS 5 สำหรับฉันด้วย บางครั้งปัญหาอาจเกิดจากแคช ในขณะที่การทดสอบวิธีการต่าง ๆ ฉันไม่สามารถบังคับให้ iOS ทำให้แคชของตนนั้นไม่สามารถใช้งานได้และเรียกคืนไฟล์ JS รุ่นใหม่ (Safari ได้ทำการเปลี่ยนแปลง แต่ไม่เพิ่มหลังจากเพิ่มแอปไปยังหน้าจอหลัก) การเปลี่ยนพอร์ตของเซิร์ฟเวอร์ dev ของฉันช่วย หากคุณมี max-age = 0 set (หรือเทียบเท่า) นี่อาจไม่ส่งผลกระทบต่อคุณ
Lukasz Korzybski

5

หากใช้ jQuery Mobile คุณจะพบหน้าต่างใหม่เมื่อใช้แอตทริบิวต์ data-ajax = 'false' ในความเป็นจริงสิ่งนี้จะเกิดขึ้นเมื่อใดก็ตามที่ ajaxEnabled ถูกปิดใช้งานโดยและลิงก์ภายนอกโดยการตั้งค่า $ .mobile.ajaxEnabled หรือโดยมีแอตทริบิวต์ target = ''

คุณสามารถแก้ไขได้โดยใช้สิ่งนี้:

$("a[data-ajax='false']").live("click", function(event){
  if (this.href) {
    event.preventDefault();
    location.href=this.href;
    return false;
  }
});

(ขอบคุณ Richard Poole สำหรับวิธีการ live () - ไม่ได้ทำงานกับ bind ())

หากคุณปิด ajaxEnabled ไปทั่วโลกคุณจะต้องวาง [data-ajax = 'false']

สิ่งนี้ใช้เวลาค่อนข้างนานในการคิดออกเพราะฉันคาดหวังว่าจะเป็นปัญหาเฉพาะ jQuery Mobile ซึ่งอันที่จริงแล้วมันเป็นการเชื่อมโยง Ajax ที่ห้ามหน้าต่างใหม่จริงๆ


เพอร์เฟ็กต์คุณช่วยฉัน :)
saulob

3

รหัสนี้ใช้ได้กับ iOS 5 (ใช้ได้กับฉัน):

ในแท็กหัว:

<script type="text/javascript">
    function OpenLink(theLink){
        window.location.href = theLink.href;
    }
</script>

ในลิงค์ที่คุณต้องการเปิดในหน้าต่างเดียวกัน:

<a href="(your website here)" onclick="OpenLink(this); return false"> Link </a>

ฉันได้รับรหัสนี้จากความคิดเห็นนี้: เมตาแท็กของเว็บแอป iphone


ด้วยเหตุผลบางอย่างฉันคิดว่านี่เป็นวิธีที่เข้าใจง่ายที่สุด
Jerrybibo

3

บางทีคุณควรอนุญาตให้เปิดลิงก์ในหน้าต่างใหม่เมื่อกำหนดเป้าหมายเป็น "_blank" อย่างชัดเจนเช่นกัน:

$('a').live('click', function (event)
{      
    var href = $(this).attr("href");

    // prevent internal links (href.indexOf...) to open in safari if target
    // is not explicitly set_blank, doesn't break href="#" links
    if (href.indexOf(location.hostname) > -1 && href != "#" && $(this).attr("target") != "_blank")
    {
        event.preventDefault();
        window.location = href;
    }

});

ขอบคุณมาก! นี่เป็นรหัสเดียวที่ใช้ได้กับ Bootstrap ของ iOS5 ที่มี Twitter มันใช้งานไม่ได้กับการผลิต
มกาญจน์

อืมไม่แน่ใจว่าทำไมมันไม่ทำงานในการผลิต แต่ฉันคิดว่ามันเป็นอย่างอื่น แจ้งให้เราทราบ!
daformat

3

ฉันพบหนึ่งที่สมบูรณ์มากและมีประสิทธิภาพเพราะตรวจสอบว่าจะทำงานภายใต้ WebApp แบบสแตนด์อโลนทำงานได้โดยไม่ต้อง jQuery และตรงไปตรงมาเพียงแค่ทดสอบภายใต้ iOS 8.2:

Stay Standalone: ​​ป้องกันลิงก์ในเว็บแอปแบบสแตนด์อโลนที่เปิด Mobile Safari


2

คุณยังสามารถทำการเชื่อมโยงได้ตามปกติ:

<a href="#" onclick="window.location='URL_TO_GO';">TEXT OF THE LINK</a>

และคุณสามารถลบแท็กแฮชและ href ทุกอย่างที่มันส่งผลกระทบต่อรูปลักษณ์ ..


2

นี่คือสิ่งที่ใช้ได้กับฉันใน iOS 6 (การปรับคำตอบ rmarscher เล็กน้อย):

<script>                                                                
    (function(document,navigator,standalone) {                          
        if (standalone in navigator && navigator[standalone]) {         
            var curnode,location=document.location,stop=/^(a|html)$/i;  
            document.addEventListener("click", function(e) {            
                curnode=e.target;                                       
                while (!stop.test(curnode.nodeName)) {                  
                    curnode=curnode.parentNode;                         
                }                                                       
                if ("href" in curnode && (curnode.href.indexOf("http") || ~curnode.href.indexOf(location.host)) && curnode.target == false) {
                    e.preventDefault();                                 
                    location.href=curnode.href                          
                }                                                       
            },false);                                                   
        }                                                               
    })(document,window.navigator,"standalone")                          
</script>

2

นี่เป็นเวอร์ชั่นที่ดัดแปลงมาเล็กน้อยของ Sean ซึ่งป้องกันปุ่มย้อนกลับ

// this function makes anchor tags work properly on an iphone

$(document).ready(function(){
if (("standalone" in window.navigator) && window.navigator.standalone) {
  // For iOS Apps
  $("a").on("click", function(e){

    var new_location = $(this).attr("href");
    if (new_location != undefined && new_location.substr(0, 1) != "#" && new_location!='' && $(this).attr("data-method") == undefined){
      e.preventDefault();
      window.location = new_location;
    }
  });
}

});


1

สำหรับผู้ที่ใช้ Twitter Bootstrap และ Rails 3

$('a').live('click', function (event) {
  if(!($(this).attr('data-method')=='delete')){
    var href = $(this).attr("href");
    event.preventDefault();
    window.location = href; 
  }   
});

ลิงก์ลบยังคงทำงานในลักษณะนี้


1

ฉันต้องการเปิดลิงก์ทั้งหมดภายในโหมดเว็บแอปแบบสแตนด์อโลนยกเว้นลิงก์ที่มี target = "_ blank" ใช้ jQuery แน่นอน

$(document).on('click', 'a', function(e) {
    if ($(this).attr('target') !== '_blank') {
        e.preventDefault();
        window.location = $(this).attr('href');
    }
});

1

วิธีแก้ปัญหาหนึ่งที่ฉันใช้สำหรับแอปพลิเคชันเว็บ iOS คือฉันสร้างลิงก์ทั้งหมด ดังนั้นฉันจึงเปิดแบบฟอร์มที่โพสต์ไปยังลิงก์ปลายทางจากนั้นป้อน type = "submit" ไม่ใช่วิธีที่ดีที่สุด แต่เป็นสิ่งที่ฉันคิดก่อนที่จะพบหน้านี้



1

สำหรับผู้ใช้JQuery Mobileวิธีการแก้ปัญหาข้างต้นจะทำลายกล่องโต้ตอบป๊อปอัพ สิ่งนี้จะทำให้ลิงก์ภายใน webapp และอนุญาตสำหรับป๊อปอัป

$(document).on('click','a', function (event) {
    if($(this).attr('href').indexOf('#') == 0) {
        return true;
    }
    event.preventDefault();
    window.location = $(this).attr('href');     
});

สามารถทำได้โดย:

$(document).on('click','a', function (event){
    if($(this).attr('data-rel') == 'popup'){
        return true;
    }
    event.preventDefault();
    window.location = $(this).attr('href');     
});

0

นี่คือสิ่งที่ฉันจะใช้สำหรับลิงก์ทั้งหมดในหน้า ...

document.body.addEventListener(function(event) {
    if (event.target.href && event.target.target != "_blank") {
        event.preventDefault();
        window.location = this.href;                
    }
});

หากคุณใช้ jQuery หรือ Zepto ...

$("body").on("click", "a", function(event) {
   event.target.target != "_blank" && (window.location = event.target.href);
});

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.