在Ionic应用中使用系统浏览器打开所有链接

16
我希望应用程序中某个特定区域内的所有链接都在系统浏览器中打开。问题是这些链接来自外部来源(API),所以我无法添加ng-click函数来帮助我在外部打开链接。 我正在使用in-app-browser插件(ng-cordova)。实际上,我有其他链接可以在外部打开,但在这种情况下,链接可以在内容的任何部分,因此我的问题是如何在加载后向所有链接添加ng-click指令?或者如果可能的话,如何配置in-app-browser插件以在系统浏览器中打开所有链接? 顺便说一句,简单的链接甚至不会在应用内浏览器中打开:我点击它们,但什么也没发生。 感谢您的帮助

你说这些链接来自API。那么为什么不使用JavaScript正则表达式,在从API获取的字符串中进行基本的搜索和替换呢? - arainone
这是唯一的方法吗?我的意思是,我可以遍历所有<a>元素,但我试图避免这样做,我认为可能有一种全局实现的方式,也许是配置应用程序内置浏览器插件之类的东西。 - Sebastian Hernandez
AngularJS 不能自动截取原生 JavaScript 调用,并且它也无法用 Angular 指令替换这些调用。 - arainone
我想知道是否可以使用inappbrowser.[loadstart]事件监听来实现这个功能?(https://github.com/apache/cordova-plugin-inappbrowser/#addeventlistener) - daserge
5个回答

6
据我所知,目前没有一种自动完成这个任务的方法,你必须使用应用内浏览器js代码来在每个平台上一致地打开外部链接。
根据你的问题描述,似乎没有明确说明服务器返回内容的示例,我假设你得到了一个完整的HTML块,并将其呈现在屏幕上。假设请求返回了类似以下的基本内容:
<div id="my-links">
   <a href='http://externallink.com'> External Link 1 </a>
   <a href='http://externallink.com'> External Link 2 </a>
   <a href='http://externallink.com'> External Link 3 </a>
</div>

您的请求看起来像这样:

$http.get('givemelinks').success(function(htmlData){
   $scope.myContent = htmlData;
})

如果您可以访问服务器端并进行更改:
在您的请求中添加“inappbrowser”参数以检测是否应返回适用于inappbrowser的链接,并更改来自服务器的响应,使其类似于以下内容:
if (inappbrowser) {
<div id="my-links">
   <div ng-click='openExternal($event)' data-external='http://externallink.com'> External Link 1 </div>
   <div ng-click='openExternal($event)' data-external='http://externallink.com'> External Link 2 </div>
   <div ng-click='openExternal($event)' data-external='http://externallink.com'> External Link 3 </div>
</div>
} else {
 <div id="my-links">
   <a href='http://externallink.com'> External Link 1 </a>
   <a href='http://externallink.com'> External Link 2 </a>
   <a href='http://externallink.com'> External Link 3 </a>
</div>
}

并拥有一个通用的 openExternal 方法:

$scope.openExternal = function($event){
  if ($event.currentTarget && $event.currentTarget.attributes['data-external'])
  window.open($event.currentTarget.attributes['data-external'], '_blank', 'location=yes');
}

如果无法更改服务器端,可解析响应并使用ng-click替换链接:
$http.get('givemelinks').success(function(htmlData){
   htmlData = htmlData.replace(/href='(.*)'/,'ng-click="openExternal($event)" data-external="$1"').replace(/<a/,"<div").replace(/a>/,"div>")
   $scope.myContent = htmlData;
})

使用与上面相同的openExternal方法。
我将anchor替换为div,以防止更改应用程序路由。但这可能并不是每个应用程序都需要的。
为了使其更好,您应该将其捆绑在“open-external”指令中,以便您可以在多个控制器中使用它并保持代码整洁。

当我尝试你的答案时,我的应用程序仍然无法打开链接。当我将 $event.currentTarget.attributes['data-external'] 记录到控制台时,我看到: data-external="http://loremipsum.com/"Window.open() 需要第一个参数是链接,而不是它前面的 data-external= 。因此我在 $event.currentTarget.attributes['data-external'] 后添加了 .value,并且当我在控制台记录它($event.currentTarget.attributes['data-external'].value)时,我只看到了链接,更重要的是当我替换 window.open() 的第一个参数时,我能够打开链接。 - Sjoerd Pottuit

2
因为在Angular中HTML已经被渲染,而inAppBrowser插件只有在通过显式Javascript调用时才起作用,因此除了手动更改HTML或使用纯Javascript之外,没有其他可行的方法。
使用正则表达式匹配来更改HTML只是一个很糟糕的想法®。
那就只剩下Javascript了:
Restangular.all('stories').getList().then(function(stories){
  $scope.stories = stories;
  updateLinks();
});

function updateLinks(){
  //use $timeout wait for items to be rendered before looking for links
  $timeout(function(){
      var $links = document.querySelectorAll(".stories .story a");
      for(var i =0; i < $links.length; i++) {
        var $link = $links[i];
        var href = $link.href;
        console.log("Hijacking link to ", href);
        $link.onclick = function(e){
          e.preventDefault();
          var url = e.currentTarget.getAttribute("href");
          window.cordova.inAppBrowser.open(url, "_system");
        }
      }
    });
}

2

2

0
<ul>
<li> <a href="#"  ng-click='openlink($event)' data-link='https://www.link1.com'> Link 1 </a></li>  
<li> <a href="#"  ng-click='openlink($event)' data-link='https://www.link2.com'> Link2 </a></li>  
<li> <a href="#"  ng-click='openlink($event)' data-link='https://www.link3.com'> Link 3 </a></li>  
</ul>

在控制器中 -
 angular.module('app', [])
    .controller('LinkCtrl', function($scope) {
         $scope.openlink = function($event)
            {               
              if ($event.currentTarget && $event.currentTarget.attributes['data-link'])
                    {
                   window.open($event.currentTarget.attributes['data-link'], '_system', 'location=yes');
                    }
                }

    })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接