Search code examples
javascriptdomevent-handlingtampermonkeymutation-observers

How can I execute a function when a div with a particular css is created?


I am developing a tampermonkey script, in order to fill a popup when this appears, this in particular.

So when the page is launched and I click a button, this creates a new popup that is a div with a particular class.

The idea is that when this popup is launched execute a piece of code to fill that popup.

I am triying with the following code:

/ ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        
// @icon         https://www.google.com/s2/favicons?domain=atlassian.net
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    document.getElementById('jira-dialog-heading').addEventListener('click', function() {
        alert('do something');
    });

})();

but doesn't work.

How can I do this?

EDIT 1

All code updated

Not errors in console

Thanks


Solution

  • From the above comment ...

    "There are two options. 1st) The OP owns the script and/or can subscribe to the popup launch process/event. In this case the OP can write and/or hook custom event handling code. 2nd) The OP does not own the script and/or can not subscribe to the popup launch process/event. In this case the OP needs to make use of a MutationObserver."

    The next provided code targets the second scenario and tries to cover the many possible but reasonable ways of how a popup could mutate the DOM ...

    // custom specific popup handling
    
    function handlePopupShow(popupNode) {
      console.log('handle popup show :: node ...', popupNode);
    }
    function handlePopupHide(popupNode) {
      console.log('handle popup hide :: node ...', popupNode);
    }
    
    
    // The popup specific mutation handler, the observers callback function.
    
    function handleChildNodeAndClassNameMutation(mutationList/*, observer*/) {
      mutationList.forEach(mutation => {
    
        const { type, attributeName } = mutation;
        if (type === 'attributes' && attributeName === 'class') {
    
          const { target } = mutation;
          if (target.matches('.popup-specific-name.show')) {
    
            handlePopupShow(target);
          } else if (
            target.matches('.popup-specific-name.hide') ||
            target.matches('.popup-specific-name:not(.show)')
          ) {
            handlePopupHide(target);
          }
        } else if (type === 'childList') {
          const {
            addedNodes: [ addedTargetNode ],
            removedNodes: [ removedTargetNode ],
          } = mutation;
          if (
            addedTargetNode?.matches?.('.popup-specific-name')
            // addedTargetNode?.matches?.('.popup-specific-name.show')
          ) {
            handlePopupShow(addedTargetNode);
          } else if (
            removedTargetNode?.matches?.('.popup-specific-name')
          ) {
            handlePopupHide(removedTargetNode);
          }
        }
      });
    }
    // - The to be observed target node.
    // - Due to detecting a popup specifc element
    //   it has to be the `document.body`.
    const popupMutationTarget = document.body;
    
    // Defines the to be observed popup specific mutations.
    const popupMutationConfig = {
      attributeFilter: ['class'],
      childList: true,
      subtree: true,
    };
    
    // Create mutation observer.
    const popupObserver =
      new MutationObserver(handleChildNodeAndClassNameMutation);
    
    // // Start target node observation for popup specific mutations.
    // popupObserver.observe(popupMutationTarget, popupMutationConfig);
    
    // // Does stop the observation.
    // popupObserver.disconnect();
    
    
    // bring test case to life.
    
    function togglePermanentPopup(/* evt */) {
      document
        .querySelector('.popup-specific-name.permanent')
        .classList.toggle('show');
    }
    function toggleNonPermanentPopup(/* evt */) {
      let popupNode =
        document.querySelector('.popup-specific-name.non-permanent');
      if (popupNode) {
        popupNode.remove();
      } else {
        popupNode = document.createElement('div');
        popupNode.classList.add('popup-specific-name', 'non-permanent');
        popupNode.textContent =
          'non permanent dom element, show and hide by insert and remove';
        document.body.prepend(popupNode);
      }
    }
    document
      .querySelector('#toggle_permanent_popup')
      .addEventListener('click', togglePermanentPopup);
    document
      .querySelector('#toggle_non_permanent_popup')
      .addEventListener('click', toggleNonPermanentPopup);
    
    let inObservation = false;
    function toggleObservation({ target }) {
      if (inObservation) {
        // Does stop the observation.
        popupObserver.disconnect();
    
        target.textContent = 'Start observation';
    
        console.log('+++ Observer disconnected +++');
      } else {
        // Start target node observation for popup specific mutations.
        popupObserver.observe(popupMutationTarget, popupMutationConfig);
    
        target.textContent = 'Stop observation';
    
        console.log('+++ Observer is running +++');
      }
      inObservation = !inObservation;
    }
    document
      .querySelector('#toggle_observation')
      .addEventListener('click', toggleObservation);
    .popup-specific-name {
      display: block;
      position: absolute;
      top: 0;
      width: 100%;
      text-align: center;
      background-color: #cf0;
    }
    .popup-specific-name.permanent {
      display: none;
      background-color: #fc0;
    }
    .popup-specific-name.show {
      display: unset;
    }
    .popup-specific-name + .popup-specific-name {
      top: 20px;
    }
    button { display: block; position: relative; top: 35px; }
    button#toggle_observation { float: right; top: 14px; }
    
    .as-console-wrapper { max-height: 111px!important; }
    <div class="popup-specific-name permanent">
      permanent dom element, class name controlled show and hide
    </div>
    
    <button id="toggle_permanent_popup">toggle permanant popup</button>
    <button id="toggle_non_permanent_popup">toggle non permanant popup</button>
    <button id="toggle_observation">Start observation</button>