AngularJS:如何在新标签中打开文件?

时间:2014-07-11 00:46:19

标签: javascript angularjs

LIVE DEMO

鉴于文件的URI,我想在新标签页(不是新窗口)中将其打开

It looks like 无法使用$window.open(uri, '_blank')

所以,我尝试了以下技巧:

var link = angular.element('<a href="uri-here" target="_blank"></a>');
angular.element(document.body).append(link);
link[0].click();
link.remove();

it works

但是,如果我在promise回调中放置完全相同的代码,它就不再起作用了(它会在新窗口中打开文件)。

知道这里发生了什么吗?

PLAYGROUND HERE

7 个答案:

答案 0 :(得分:11)

从您的代码/内容中,您无法强制浏览器打开新标签页(而不是新窗口,反之亦然)。这取决于浏览器设置,以某种方式强制它。

其他任何事都会带来安全风险。

答案 1 :(得分:4)

让我们了解弹出窗口阻止程序的工作原理。

如果用户触发该功能打开一个新的网址,那么弹出阻止程序将允许它(它应该应用于任何现代浏览器 - 至少是firefox,chrome)

如果不是来自用户(如后台的javascript函数,承诺或任何其他功能不是来自用户),浏览器将阻止,除非用户手动将站点列入白名单。

这不起作用。

function openInNewTab() {
    window.open('http://stackoverflow.com','_blank');
}

openInNewTab();//fail

这是有效的

<h1><button onclick="openInNewTab()">Open In New Tab - working</button></h1>

我创建了简单的plunkr版本 - http://plnkr.co/edit/QqsEzMtG5oawZsQq0XBV?p=preview

所以,回答你的问题。除非用户授权它(用户触发它或白色列出该站点),否则是不可能的。

引自firefox -

  

弹出窗口或弹出窗口是自动显示的窗口   未经您许可。

https://support.mozilla.org/en-US/kb/pop-blocker-settings-exceptions-troubleshooting

*在新标签页/新窗口中打开没有任何区别。弹出窗口阻止程序仍将始终阻止。它并不意味着如果在新标签页中打开,浏览器将允许。对于某些浏览器默认以这种方式设置是巧合的。

解决方法

在后台执行后,您可以明确要求用户触发在新选项卡中打开的功能 您可以在UI中显示消息,要求用户打开该URL。 示例 - http://plnkr.co/edit/iyNzpg64DtsrijAGbHlT?p=preview

答案 2 :(得分:2)

您只能在用户触发的click事件处理程序中打开新窗口。

原因是可用性

我不确定所有浏览器是否都有此行为,但某些浏览器不允许脚本打开Windows 而不会引起用户注意。想象一下,当您访问网页时,网页会突然打开几个窗口=&gt;这很烦人。

请参阅此DEMO(使用我的Chrome和Firefox测试过),即使我们按脚本触发点击事件,浏览器仍会阻止弹出窗口。

$("#test").click(function(){
    openInNewTab();
});

$("#test").click();

您无法在ajax成功回调中打开一个新窗口,因为您的ajax成功是在单击事件处理程序完成执行后的另一个循环中运行的。

有关解决方法的信息,请参阅此link

  

如果我在promise回调中输入完全相同的代码,它就不起作用   不再(它在新窗口中打开文件)。

我很惊讶您仍然可以打开一个新窗口。但是这个问题确实与用户触发的点击事件有很多关系

答案 3 :(得分:1)

你的问题是双重的,两个折叠都在不确定的领域。


在过去的浏览器中,window.open就是这样做了 - 打开一个新窗口。那是因为标签的概念尚未发明。当引入标签时,它们的处理方式与窗口完全相同,以提高兼容性,而这种传统一直持续到今天。那个以及window.open仅为standardized very recently的事实意味着JavaScript无法区分窗口和标签。

没有“正常”的方式来指定链接是否应在新标签页中打开。但是可以使用以下hack:指定open调用的自定义窗口大小(通过第三个参数),如下所示:

window.open('http://example.com', '', 'width=' + screen.width);

这会导致几乎所有浏览器都打开一个单独的窗口,因为标签不能有自定义大小。


在JavaScript中,有受信任的事件和不受信任的事件。例如,可信事件是用户对链接的合法点击,而不受信任的事件则是对链接的手动click()调用。

只有受信任的事件处理程序才能打开新的窗口/标签。这是为了防止客户端攻击导致浏览器崩溃或通过在mouseover或类似内容上快速打开一百个标签来混淆用户。

您的第二个示例不起作用,因为弹出窗口阻止程序会阻止您通过click()触发的不受信任事件。虽然它是由真正的点击引起的,但是中间的异步调用会切断到可信度的链接。

答案 4 :(得分:0)

working version

$http.get('https://api.github.com/users/angular').then(openInNewTab());

EDIT ----------------

不知道为什么但是从回调函数调用的click()方法与直接调用它的方式不同。

您可以在此处看到设置间隔示例。

这就是为什么我直接调用函数而不是通过回调。

see it with timer callback

答案 5 :(得分:0)

或者您可以使用$ window服务,请参阅此处:http://plnkr.co/edit/8egebfFj4T3LwM0Kd64s?p=preview

angular.module("Demo", []).controller("DemoCtrl", function($scope, $http, $window) {
  $scope.uri = 'http://martinfowler.com/ieeeSoftware/whenType.pdf';

  function openInNewTab() {

    var link = angular.element('<a href="' + $scope.uri + '" target="_blank"></a>');

    angular.element(document.body).append(link);

    link[0].click();
    link.remove();
  }

  $scope.works = openInNewTab;

  $scope.doesntWork = function() {
    $http.get('https://api.github.com/users/angular').then($window.open($scope.uri));
  };
});

答案 6 :(得分:0)

对我们来说,以下效果很好:http://blog-it.hypoport.de/2014/08/19/how-to-open-async-calls-in-a-new-tab-instead-of-new-window-within-an-angularjs-app/

简而言之:我们记得对新窗口的引用以及之后更改位置。