0

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 webpack generated javascript file there would be something like which would not be easy to find and read minified code.

var button = document.querySelctor('653cde4c-1620-11ec-85b5-5ae26c154b46')
// Add whatever you want to add to this button element, e.g. add onClick() or submit() or something else which I am not sure of

We can see image at https://i.stack.imgur.com/8oG5w.png

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?

Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
Alok
  • 7,734
  • 8
  • 55
  • 100
  • `return false` in event handler ? – Dominik Matis Sep 16 '21 at 13:40
  • Check this [link](https://stackoverflow.com/questions/17169198/how-to-disable-or-hide-the-open-in-new-tab-option-for-hyperlinks). – Toni Sep 16 '21 at 13:43
  • I think OP wants to disable opening new tab/window, not prevent the click @DominikMatis – Cjmarkham Sep 16 '21 at 13:44
  • Is there at least any pattern (like a specific element with at least one specific attribute) from which one could recognize such a trigger / such an element? – Peter Seliger Sep 16 '21 at 14:46
  • @PeterSeliger: I am not sure, I have added screenshot and edited question – Alok Sep 16 '21 at 15:02
  • @AlokSinghMahor ... ok, we have a button with an invalid `id`entifier and a `className` value one most probably can also not rely on. The plan is to globally listen to `'click'` events and for any button-click to immediately stop the propagation. Does such radical approach effect any other `button` triggered behavior? – Peter Seliger Sep 16 '21 at 15:11
  • @AlokSinghMahor ... Another approach is to wrap a function around `window.open` providing additional logic which does intercept and analyze every single invocation of `open`. – Peter Seliger Sep 16 '21 at 15:15
  • @PeterSeliger: Thanks for these clues to try :) – Alok Sep 16 '21 at 15:20

2 Answers2

1

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>
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
  • @AlokSinghMahor ... are there any questions left regarding both above provided approaches? – Peter Seliger Sep 17 '21 at 13:41
  • Thanks a lot for answer. This answer gave me clues to build approch to solve my problem. I have up voted your answer. Can your approch help my problem where I dont have `data-url` in ` – Alok Sep 18 '21 at 08:08
  • @AlokSinghMahor ...I suppose you talk about the event delegation based approach. The `data-*` attributes where only for demonstration purposes in order to mimic the third-party button-click triggered hyperlink-behavior. Thus you need to figure out yourself how to best identify the event source that then has to be stopped with propagating the event any further. A viable identification might already be the check for the special pattern of a button's `id`' in combination with the structure of such a button, like there is always a `
    ` with another `id` attribute embedded within a ``.
    – Peter Seliger Sep 18 '21 at 10:09
0

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.

Konstantin Dinev
  • 34,219
  • 14
  • 75
  • 100