-1

I've been working on an issue with my program executing too quickly to detect whether popup is being blocked by the browser. Even with the timeout, sometimes the window that is opened doesn't get closed. I've also tried opening a window and passing a value back to the parent window and that didn't work either.

setTimeout(DetectPopUp(), 1000);

function DetectPopUp() {
  var puTest = setTimeout(window.open("", "", "width=1,height=1,top=2000"));
    
  try {
    puTest.close();
    return false;
  } catch (e) {
    return true;
  }
}

Any ideas on how to do this?

Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
bluesky
  • 624
  • 2
  • 14
  • 25
  • 2
    1. `puTest` will not be the window you opened, it'll be the identifier returned by `setTimeout` - 2. `setTimeout` takes a function as it's first argument, you're providing the result of calling a function - i.e. do `setTimeout(DetectPopUp, 1000);` and remove the setTimeout inside that function altogether - here's [setTimeout documentation](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) – Jaromanda X Mar 02 '23 at 01:11
  • @JaromandaX Thanks for the suggestion. Unfortunately, the same issue occurs every now and then. – bluesky Mar 02 '23 at 01:50
  • 1
    If this isn't the code that you're actually running it's impossible to guess what the current problem might be. – Dave Newton Mar 02 '23 at 02:15
  • I'm guessing you still probably wrote it wrong – Jaromanda X Mar 02 '23 at 02:30
  • You need to timeout the close action, not the opening of the window. The problem is that in order to do so, the function cannot return immediately. What you are attempting to do, it's an async action, you should use promises or async / await to get this working. – chq Mar 02 '23 at 02:47

1 Answers1

0

As already mentioned the source of the OP's currently failing code is how the OP uses setTimeout and its return value. The latter is not the handle of a window reference as the OP seems to assume but the timeout specific identifier which can be used for e.g. canceling the timeout before the execution of the to be delayed code happens.

Thus, the OP actually does not need to write a deferred version of a popup blocker test since window.open immediately returns the result of its action which either is a Window object (no popup blocker) or is the null value (most probably due to a popup blocker).

But of cause one could come up with promise based test functionality implemented as a single async function which then can be utilized either as chained promise or within another async function by the await operator.

async function promisedPopupBlockerTest() {
  return new Promise((resolve, reject) => {
    try {
      const result = { hasBlocker: true }; // result default.

      const handle = window.open('', '', 'popup=true,width=1,height=1,top=2000');
      if (!!handle) {

        handle.close();
        result.hasBlocker = false; // result value change.
      }
      resolve(result); // resolve always with a valid result.

    } catch (reason) {

      reject(reason); // reject for/with whatever reason.
    }
  });
}

// ... usage as ...

// ... either chained promise ...
promisedPopupBlockerTest()
  .then(result => console.log(`resolved with ${ JSON.stringify(result) }`))
  .catch(reason => console.log(`rejected with ${ JSON.stringify(reason) }`));

// ... or with async...await syntax ...
(async () => {
  const result = await promisedPopupBlockerTest();
  console.log('awaited test result ... ', result);
})();

// prove of the popup blocking behavior of SO sandboxes.
const handle = window.open('', '', 'popup=true,width=1,height=1,top=2000');
console.log({ handle });
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37