Home > Enterprise >  How does one prevent the opening of a new tab or window when hyperlink behavior was created virtuall
How does one prevent the opening of a new tab or window when hyperlink behavior was created virtuall

Time:09-18

I can disable opening new tab or window in case of <a> tag by removing target attribute e.g. target='_blank'

In some cases instead of <a> website put <button> and add onClick() or submit() etc which programmatically generates a link and sets the target attribute.

<button id="653cde4c-1620-11ec-85b5-5ae26c154b46">
    <div>click here</div>
</button>

In some enter image description here

In such case where <button> is providing link click functionality. I can not view and edit onClick() or submit() etc as its webpack generated javascript. I can only run my javascript code after loading of that webapge in devtools console.

How can I disable opening new tab or new window of browser in such case? Or What javascript code should I run to override <button> link behaviour?

CodePudding user response:

Probably the logic in the onClick() does something like window.open(url, [params]). You can change this to setting window.location.href = url; and the url will be loaded in the same window.

CodePudding user response:

Depending on how the webpack based code does manage the tab handling of resources one possible solution was to wrap own code around window.open or even entirely replace it with an own implementation.

As for the wrapping, based on the intercepted data, one could decide of whether one does suppress the url-handling entirely or, instead of opening a new tab/window, does a forwarding to location.href or even proceed with invoking the original window.open.

// untouchable 3rd party code
//
function alienLocationHandler({ currentTarget }) {
  let { url, target } = currentTarget.dataset;

  url = (url ?? '').trim();
  if (url) {

    target = (target ?? '').trim();
    if (target) {

      // due to SO's permission handling ...
      //
      // ... Blocked opening 'https://stackoverflow.com/' in a
      // new window because the request was made in a sandboxed
      // frame whose 'allow-popups' permission is not set.
      //
      window.open(url, target);
    } else {
      window.location.href = url;
    }
  }
}
document
  .querySelectorAll('[data-url]')
  .forEach(elmNode =>
    elmNode.addEventListener('click', alienLocationHandler)
  );


// one possible approach :: wrap around `window.open`
//
window.open = (function createAroundHandler(proceed, thisArg) {
  return function aroundWindowOpen(url, target, ...rest) {

    console.log('aroundWindowOpen ...', {
      url,
      target,
      rest,
    });

    // - of cause all the code is just for demonstration purpose.
    //
    // - the OP has to come up with own handler logic which does
    //   fit the OP's needs best.
    
    if (url !== 'https://stackoverflow.com') {

      // invocation of the original `window.open`
      // will be blocked by SO's permission handling.

      proceed.call(thisArg, url, target, ...rest);

    } else {
      // delayed fowarding to `location.href`.

      setTimeout(() => { window.location.href = url }, 5000);
    }
  };
}(window.open, window));
body { margin: 0; }
.as-console-wrapper { min-height: 87%; top: auto; }
<button data-url="https://stackoverflow.com">
  no interception
</button>

<button
  data-url="https://google.com"
  data-target='google'
  >
  intercepted &amp; open attempt  
</button>

<button
  id="_653cde4c-1620-11ec-85b5-5ae26c154b46"
  data-url="https://stackoverflow.com"
  data-target='_blank'
  >
  intercepted and forwarded with 5sec delay
</button>

Another approach was to make use of event delegation by listening to and handling click events at e.g. document.body level.

// untouchable 3rd party code
//
function alienLocationHandler({ currentTarget }) {
  let { url, target } = currentTarget.dataset;

  url = (url ?? '').trim();
  if (url) {

    target = (target ?? '').trim();
    if (target) {

      // due to SO's permission handling ...
      //
      // ... Blocked opening 'https://stackoverflow.com/' in a
      // new window because the request was made in a sandboxed
      // frame whose 'allow-popups' permission is not set.
      //
      window.open(url, target);
    } else {
      window.location.href = url;
    }
  }
}
document
  .querySelectorAll('[data-url]')
  .forEach(elmNode =>
    elmNode.addEventListener('click', alienLocationHandler)
  );


// another possible approach :: event delegation
//
// - [https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_delegation]
// - [https://davidwalsh.name/event-delegate]
//
// - [https://javascript.info/event-delegation]
// - [https://learn.jquery.com/events/event-delegation/]
//
function isButtonEvent(activeElement, targetNode) {
  return (activeElement.tagName.toLowerCase() === 'button') && (
    activeElement.isSameNode(targetNode) ||
    activeElement.contains(targetNode)
  );
}
function preventSpecificButtonClickBehavior(evt) {
  const elmButton = document.activeElement;

  if (isButtonEvent(elmButton, evt.target)) {
    const url = (elmButton.dataset.url ?? '').trim();

    const isUrlBasedPrevented = (url !== 'https://stackoverflow.com');
    const isIdBasedPrevented = ((elmButton.id ?? '').trim() !== '');

    if (isUrlBasedPrevented || isIdBasedPrevented) {
      evt.stopImmediatePropagation();
      evt.stopPropagation();

      if (isUrlBasedPrevented) {
        console.log('prevented button click behavior ... URL based')
      }
      if (isIdBasedPrevented) {
        console.log('prevented button click behavior ... ID based')
      }
    }
  }
}
document
  .body
  .addEventListener(
    'click',
    preventSpecificButtonClickBehavior,
    // - [https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#parameters]
    // - The boolean `useCapture` parameter/flag does the trick if set as `true` value.
    true
  );
body { margin: 0; }
.as-console-wrapper { min-height: 87%; top: auto; }
<button data-url="https://stackoverflow.com">
  click behavior not prevented
</button>

<button
  id="_653cde4c-1620-11ec-85b5-5ae26c154b46"
  data-url="https://stackoverflow.com"
  >
  prevented behavior (id based)
</button>

<button
  data-url="https://google.com"
  data-target='google'
  >
  <span>
    <span>
      prevented behavior (url based)
    </span>
  </span>
</button>

  • Related