JQuery event.preventDefault ()가 설정된 경우 window.open에서 팝업 차단기 무시


98

하이퍼 링크의 클릭 이벤트에 조건부로 JQuery 대화 상자를 표시하고 싶습니다.

condition1에서 JQuery 대화를 열고 condition1이 충족되지 않으면 해당 클릭 이벤트가있는 'href'태그가 참조하는 페이지로 이동합니다.

링크 클릭 이벤트에 대한 함수를 호출 할 수 있습니다. 이 함수는 이제 다른 URL을 실행하여 해당 조건을 확인합니다 (내 Spring 컨트롤러를 실행하고 응답을 반환 함).

팝업 차단기에 의해 차단되는 window.open 만 완벽하게 작동합니다.

$('a[href*=/viewpage?number]').live('click', function(e) {
    e.preventDefault();
    redirectionURL = this.href;
    pageId= getUrlVars(redirectionURL)["number"];
    $.getJSON("redirect/" + pageId, {}, function(status) {
        if (status == null) {
            alert("Error in verifying the status.");
        } else if(!status) {
            $("#agreement").dialog("open");
        } else {
            window.open(redirectionURL);
        }
    });
});

e.preventDefault();코드에서 제거하면 팝업 차단기가 페이지를 차단하지 않지만 condition1의 경우 대화 상자를 열고 'href'페이지를 엽니 다.

하나를 해결하면 다른 문제가 발생합니다. 나는 두 가지 조건을 동시에 정의 할 수 없습니다.

이 문제를 해결하도록 도와 주시겠습니까?

이 문제가 해결되면 해결해야 할 또 다른 문제가 있습니다. 예를 들어 대화의 OK 이벤트 탐색 :)


1
.live를 사용하지 말고 .on ()에 대한 포인터를 사용하십시오!
mas-designs

@EvilP : 다른 사람들이 지난번에 말했듯이 1.7 이상에서만 가능합니다. 많은 프로젝트는 여전히 1.5 또는 1.6에있을 것입니다.
TJ Crowder

10
Downvoter : 팝업이 마음에 들지 않는다고해서이 질문에 반대 투표를해야한다는 의미는 아닙니다. 질문이 "... 연구 노력을 보여주지 않는 경우, 불분명하거나 유용하지 않은 경우 "에 대해 반대 투표를해야합니다 . 질문은 분명하고 게으른 것처럼 보이지 않으며 사소하지 않은 요인 조합에서 비롯됩니다.
TJ Crowder

@TJCrowder : 그는 그가 사용하는 버전을 지정하지 않았습니다. 그래서 나는 그가 최신 버전을 사용하고 있다는 것을 고려해야합니다. 그가 다른 버전을 사용하고 있다면 그는 live가 더 이상 사용되지 않는다는 사실을 인식하고 그가 .live ()를 사용하는 이유를 설명 할 것이기 때문에 그가 언급 할 것이라고 확신합니다. 아무도 나에게 "마지막"시간을 말하지 않았으므로 휴식을 취하고 진정해야한다고 생각합니다. 너무 가혹한 될 필요가 ... 없다
마스 - 디자인

그것에 대한 알림을받지 못했습니다. 그러나 누군가가 최신 버전을 사용하고 있다고 생각하기 위해 자신의 버전을 지정하지 않으면 고려하는 것이 일반적이지 않습니까? 1.3을 사용해야하는 이유가 있고 새롭고 더 나은 버전이 있다는 사실을 알고 있습니다.
mas-designs

답변:


144

팝업 차단기는 일반적으로 사용자 이벤트 (예 : 클릭)를 처리 window.open하는 동안 사용 되는 경우 에만 허용 합니다 . 귀하의 경우에는 비동기 이기 때문에 이벤트 도중이 아니라 window.open 나중에 호출 $.getJSON합니다.

두 가지 옵션이 있습니다.

  1. 대신 다른 작업을 수행하십시오 window.open.

  2. ajax 호출을 동기식으로 만드십시오. 이는 브라우저의 UI를 잠그기 때문에 일반적으로 전염병처럼 피해야하는 것입니다. $.getJSON다음과 같습니다.

    $.ajax({
      url: url,
      dataType: 'json',
      data: data,
      success: callback
    });

    ... 그리고 $.getJSON위의 매개 변수를 매핑하고 다음을 추가 하여 호출을 동기식으로 만들 수 있습니다 async: false.

    $.ajax({
        url:      "redirect/" + pageId,
        async:    false,
        dataType: "json",
        data:     {},
        success:  function(status) {
            if (status == null) {
                alert("Error in verifying the status.");
            } else if(!status) {
                $("#agreement").dialog("open");
            } else {
                window.open(redirectionURL);
            }
        }
    });

    다시 말하지만, 목표를 달성하는 다른 방법을 찾을 수 있다면 동기식 아약스 호출을 옹호하지 않습니다. 하지만 할 수 없다면 거기에 간다.

    다음은 비동기 호출로 인해 테스트에 실패한 코드의 예입니다.

    라이브 예 | 라이브 소스 (JSBin 변경으로 인해 라이브 링크가 더 이상 작동하지 않음)

    jQuery(function($) {
      // This version doesn't work, because the window.open is
      // not during the event processing
      $("#theButton").click(function(e) {
        e.preventDefault();
        $.getJSON("http://jsbin.com/uriyip", function() {
          window.open("http://jsbin.com/ubiqev");
        });
      });
    });

    다음은 동기식 호출을 사용하여 작동하는 예입니다.

    라이브 예 | 라이브 소스 (JSBin 변경으로 인해 라이브 링크가 더 이상 작동하지 않음)

    jQuery(function($) {
      // This version does work, because the window.open is
      // during the event processing. But it uses a synchronous
      // ajax call, locking up the browser UI while the call is
      // in progress.
      $("#theButton").click(function(e) {
        e.preventDefault();
        $.ajax({
          url:      "http://jsbin.com/uriyip",
          async:    false,
          dataType: "json",
          success:  function() {
            window.open("http://jsbin.com/ubiqev");
          }
        });
      });
    });

3
정말 감사합니다. 통화를 동기식으로 만드는 제안은 매력처럼 작동했습니다. 대화의 OK 이벤트에서 내비게이션을 처리하는 다음 호에서 동일한 내용이 도움이되었습니다.
mavaze

TJ Crowder가 2 개의 질문을 열어 두었 기 때문에 [1. window.open] 및 [2. [Ajax 동기 호출 방지] 제안에 대한 커뮤니티의 이익을 위해 환영합니다. 그렇지 나는 그의 대답을 발견하기위한 완벽한 솔루션 질문 :) 말했다
mavaze

4
저에게는 target = "_ blank"링크를 추가하여 사용자에게 클릭하라는 메시지를 표시했습니다.
hiroshi

1
@Evan : XHR을 직접 사용해야합니다. 티켓에 동기 요청 지원 중단 에 대한 예가 있습니다 .
TJ Crowder 2012-06-25

2
@mavaze 먼저 창을 열고 (동기화), AJax 요청 (비동기)을 수행 한 다음 응답을 사용하여 오류 메시지를 표시하거나 리디렉션을 수행하도록 제어 흐름을 변경할 수 있다면 두 가지 문제를 모두 피할 수 있다고 생각합니다.
Stijn de Witt

61

사용자가 직접 작업을 수행하는 경우에만 브라우저 차단없이 window.open을 호출 할 수 있습니다. 브라우저는 일부 플래그를 보내고 사용자 작업에 의해 열린 창을 결정합니다.

따라서이 시나리오를 시도해 볼 수 있습니다.

  1. var myWindow = window.open ( '')
  2. 이 창에 로딩 메시지를 그립니다.
  3. 요청이 완료되면 myWindow.location = ' http://google.com '을 호출하십시오.

2
이것은 Safari Mobile에서 작동하지 않습니다 (iPhone 4에서 테스트 됨). 몇 가지 다른 아이디어 (예 myWindow.postMessage:)를 시도했지만 백그라운드에서 JavaScript를 실행하지 않는 Safari의 제한으로 인해 부모 창에서 해당 위치 변경을 보낼 수 없습니다.
Roundrobin 2014 년

@BausTheBig IPhone 6, IOS8에서 테스트했습니다. 그것은 매력처럼 작동했습니다.
lvarayut

팝업을 차단하지 않고 Google Analytics로 외부 링크를 추적하는 방법을 찾고있었습니다. 이것이 바로 제가 필요로하는 것입니다. iOS7 (실제 전화) 및 iOS 8 (iOS 시뮬레이터)의 iPhone 4s에서 잘 작동하는 것 같습니다.
notacouch 2011 년

37

이 문제가 있었고 콜백이 일부 데이터를 반환 할 때까지 URL이 준비되지 않았습니다. 해결책은 콜백을 시작하기 전에 빈 창을 연 다음 콜백이 반환 될 때 위치를 설정하는 것입니다.

$scope.testCode = function () {
    var newWin = $window.open('', '_blank');
    service.testCode().then(function (data) {
        $scope.testing = true;
        newWin.location = '/Tests/' + data.url.replace(/["]/g, "");
    });
};

1
나는 새 창을 열려면이 솔루션을 사용하고 popupblocker 우회
VeldMuijz

팝업을 열어야하는지 미리 모르는 경우 어떻게해야합니까? 에서와 같이 : action().then(doWindowOpenThing).catch(doSomethingElseThatDoesntOpenAPopup) 나중에 사용하지 않을 경우 참조를 유지하기 위해 미리 창을 열 수 없습니다.
Luiz

아니 그것은 매번 새 탭을 열 것이며 사용하지 않는 경우에는 원하지 않을 것이라고 생각합니다. 문제는 브라우저가 클릭 기능 (사용자 시작 작업)에서 새 탭을 열 수 있도록 허용한다는 것입니다. 그렇지 않으면 팝업 차단기가이를 사용자 권한없이 새 탭을 여는 스크립트로보고 차단합니다.
KnuturO

newWin이 null인지 테스트하십시오!
FrancescoMM

왜 ? 그럴 이유가 없습니다.
KnuturO

18

이것을 시도해보십시오.

$('#myButton').click(function () {
    var redirectWindow = window.open('http://google.com', '_blank');
    $.ajax({
        type: 'POST',
        url: '/echo/json/',
        success: function (data) {
            redirectWindow.location;
        }
    });
});

이것에 대한 바이올린입니다 http://jsfiddle.net/safeeronline/70kdacL4/1/


1
고마워, 나도 위해 일했다-그 바이올린이 아니었다면 아마 믿지 않았을 것입니다.
rmcsharry

3
이것이 받아 들여진 대답이어야합니다! URL을 작성하기 위해 비동기 데이터가 필요한 경우 redirectWindow.location.assign ( 'new_url')을 사용할 수도 있습니다.
matheusr

Nice solution.keep it up
Shah NIral

redirectWindow가 null인지 테스트하십시오! 다른 브라우저 옵션에 따라 차단되거나 차단 될 수 있습니다.
FrancescoMM

8

Windows는 사용자가 시작한 이벤트 (예 : 클릭 콜백)와 동일한 스택 (일명 microtask ) 에 생성되어야합니다. 따라서 나중에 비동기식으로 생성 할 수 없습니다.

그러나 URL없이 창을 생성 한 다음 해당 창 URL을 알고 나면 해당 창 URL을 변경할 수 있습니다. 비동기 적으로도 .

window.onclick = () => {
  // You MUST create the window on the same event
  // tick/stack as the user-initiated event (e.g. click callback)
  const googleWindow = window.open();

  // Do your async work
  fakeAjax(response => {
    // Change the URL of the window you created once you
    // know what the full URL is!
    googleWindow.location.replace(`https://google.com?q=${response}`);
  });
};

function fakeAjax(callback) {
  setTimeout(() => {
    callback('example');
  }, 1000);
}

최신 브라우저는 빈 페이지 (종종라고 함 about:blank)가 있는 창을 열고 URL을 가져 오는 비동기 작업이 상당히 빠르다고 가정하면 결과 UX는 대부분 괜찮습니다. 대신 사용자가 기다리는 동안 로딩 메시지 (또는 기타)를 창에 렌더링하려면 데이터 URI를 사용할 수 있습니다 .

window.open('data:text/html,<h1>Loading...<%2Fh1>');

3

이 코드는 나를 도와줍니다. 이것이 어떤 사람들에게 도움이되기를 바랍니다.

$('formSelector').submit( function( event ) {

    event.preventDefault();

    var newWindow = window.open('', '_blank', 'width=750,height=500');

    $.ajax({

        url: ajaxurl,
        type: "POST",
        data: { data },

    }).done( function( response ) {

        if ( ! response ) newWindow.close();
        else newWindow.location = '/url';

    });
});

3

링크 요소를 사용 해보고 javascriipt로 클릭하십시오.

<a id="SimulateOpenLink" href="#" target="_blank" rel="noopener noreferrer"></a>

및 스크립트

function openURL(url) {
    document.getElementById("SimulateOpenLink").href = url
    document.getElementById("SimulateOpenLink").click()
}

이렇게 사용하세요

//do stuff
var id = 123123141;
openURL("/api/user/" + id + "/print") //this open webpage bypassing pop-up blocker
openURL("https://www.google.com") //Another link

이것은 나를 위해 빈 창을 다루는 것을 피했습니다.
ponder275

iPhone이 내 창을 팝업으로 차단하는 문제가 해결되지 않은 것으로 나타났습니다.
ponder275

2

사용자가 이벤트를 시작해야한다는 관찰은 첫 번째 부분을 파악하는 데 도움이되었지만 그 후에도 Chrome과 Firefox가 새 창을 차단했습니다. 두 번째 부분은 링크에 target = "_ blank"를 추가하는 것으로 한 댓글에서 언급했습니다.

요약하면, 사용자가 시작한 이벤트에서 window.open을 호출해야합니다.이 경우 링크를 클릭하면 해당 링크에 target = "_ blank"가 있어야합니다.

아래 예에서 링크는 class = "button-twitter"를 사용하고 있습니다.

$('.button-twitter').click(function(e) {
  e.preventDefault();
  var href = $(this).attr('href');
  var tweet_popup = window.open(href, 'tweet_popup', 'width=500,height=300');
});


1

내 React 코드에서 팝업 차단기를 피하기 위해이 방법을 사용하고 있습니다. 다른 모든 자바 스크립트 코드에서도 작동합니다.

클릭 이벤트에서 비동기 호출을 할 때 먼저 빈 창을 연 다음 나중에 비동기 호출이 완료 될 때 URL을 작성합니다.

const popupWindow = window.open("", "_blank");
popupWindow.document.write("<div>Loading, Plesae wait...</div>")

비동기 호출이 성공하면 다음을 작성하십시오.

popupWindow.document.write(resonse.url)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.