Ответ 1
Из вашего кода/содержимого вы не можете заставлять браузер открывать новую вкладку (а не новое окно или наоборот). Это зависит от настроек браузера, чтобы заставить его так или иначе.
Все остальное будет представлять угрозу безопасности.
Учитывая URI файла, я хотел бы открыть его на новой вкладке (не в новом окне).
Похоже, что невозможно использовать $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();
и он работает.
Но если я ставлю точно такой же код в обратном вызове с обещаниями, он больше не работает (вместо этого он открывает файл в новом окне).
Любая идея, что здесь происходит?
Из вашего кода/содержимого вы не можете заставлять браузер открывать новую вкладку (а не новое окно или наоборот). Это зависит от настроек браузера, чтобы заставить его так или иначе.
Все остальное будет представлять угрозу безопасности.
Давайте понимать, как работает блокировщик всплывающих окон.
Если пользователь запускает функцию для открытия нового URL-адреса, то всплывающее блокирование позволит это (оно должно применяться к любому современному браузеру - по крайней мере, 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
* Открыть новую вкладку/новые окна не имеет никакого значения. Блокировщик всплывающих окон все равно будет блокироваться. Это не означает, что браузер разрешит открытие на новой вкладке. Совсем случайно для некоторых браузеров по умолчанию настроены таким образом.
Обход
Вы можете попросить пользователя явно вызвать функцию для открытия на новой вкладке после выполнения фона.
Вы можете отобразить сообщение в пользовательском интерфейсе, чтобы попросить пользователя открыть URL-адрес.
Пример - http://plnkr.co/edit/iyNzpg64DtsrijAGbHlT?p=preview
Вы можете открывать только новые окна внутри click
обработчиков событий , запускаемых пользователем.
Причиной этого является юзабилити.
Я не уверен, что все браузеры имеют такое поведение, но некоторые браузеры не позволяют сценариям открывать окна без уведомления пользователя. Представьте себе, когда вы посещаете веб-страницу, и вдруг веб-страница открывает несколько окон = > это раздражает.
Смотрите DEMO (протестировано с моим Chrome и Firefox), даже мы запускаем событие click с помощью script, браузер все еще блокирует всплывающее окно.
$("#test").click(function(){
openInNewTab();
});
$("#test").click();
Вы не можете открыть новое окно в своем обратном вызове ajax, потому что ваш успех ajax запускается в другом цикле после завершения обработчика события click.
См. ссылку для обхода
Если я поставлю точно такой же код в обратном вызове обещания, он не работает (вместо этого он открывает файл в новом окне).
Я удивлен, что вы все еще можете открыть новое окно. Но эта проблема действительно имеет много общего с событиями click, которые запускаются пользователем.
Ваша проблема в два раза, и обе складки прогибаются на неопределенной территории.
В старые времена браузеров window.open
сделал именно это. – открыть новое окно. Это потому, что концепция вкладок еще не была изобретена. Когда были введены вкладки, они обрабатывались точно так же, как окна, чтобы улучшить совместимость, и эта традиция продолжается и по сей день. Это и тот факт, что window.open
был только стандартизован совсем недавно, означает, что JavaScript не может различать окна и вкладки.
Нет никакого "нормального" способа указать, должна ли ссылка открываться на новой вкладке или нет. Однако вы можете использовать следующий хак: укажите размер настраиваемого окна для вызова open
(через третий аргумент), например:
window.open('http://example.com', '', 'width=' + screen.width);
Это приведет к тому, что почти все браузеры откроют отдельное окно, потому что вкладки не могут иметь пользовательские размеры.
В JavaScript есть доверенные события и ненадежные события. Надежными событиями являются, например, законные клики по ссылке пользователя, тогда как ненадежным событием будет ручной вызов click()
по ссылке.
Только доверенные обработчики событий могут открывать новые окна/вкладки. Это предотвращает атаки на стороне клиента, которые приводят к краху браузера или путают пользователя, быстро открывая сто вкладок на mouseover
или что-то подобное.
Ваш второй пример не работает, потому что блокиратор всплывающих окон блокирует ненадежное событие, которое вы запускали с помощью click()
. Хотя это вызвано реальным щелчком, асинхронный вызов между ними отключает ссылку на доверенность.
$http.get('https://api.github.com/users/angular').then(openInNewTab());
ИЗМЕНИТЬ ----------------
Не знаю, почему, но метод click(), вызванный из функции обратного вызова, действует иначе, чем называть его прямым.
Здесь вы можете увидеть пример с заданным интервалом.
Вот почему я вызывал функцию напрямую, а не выполнял обратный вызов.
или вы можете использовать услугу $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));
};
});
Для нас хорошо сработало следующее: 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/
Вкратце: мы помним ссылку на новое окно и впоследствии меняем местоположение.