skip to Main Content

I want to lookup some data inside a tag, I do not know if the tag would be a <div> or a <p> or a <span> or any other text element tag. Other than reading the data, I want to record where the relevant tag is to be found inside a page. Here is an example:

<div id="myDiv">
    <p>irrilevant data</p>
    <p>Interesting data</p>
</div>

When the user right click the relevan data of interest, I need to record the relevant data as also where this data is in the DOM considering the first parent, for example I wrote this and it is working fine:

<script>
    // Function to handle global right-click
    function handleGlobalRightClick(event) {
        // Get the clicked element
        let clickedElement = event.target;

    if (!clickedElement.id){
       //the element has no id i need to find the nth 
           let clickedElementParent = event.target.parentElement;
           // Traverse up the DOM hierarchy to find the first element with an id
       while (!clickedElementParent.id) {
          clickedElementParent = clickedElementParent.parentElement;
           }

           // If the clicked element has a parent and it has multiple children, find the index
           let childIndex = null;
           if (clickedElementParent && clickedElementParent.children.length > 1) {
               const childNodes = clickedElementParent.children;
               for (let i = 0; i < childNodes.length; i++) {
                   if (childNodes[i] === clickedElement) {
                       childIndex = i;
                       break;
                   }
               }

            // Log or use the id and index of the clicked element
            console.log(`Parent Id: ${clickedElementParent.id}`);
            console.log(`Child Index: ${childIndex}`);

           }

    } else {
        //the element has an id, problem solved
    }

    }

</script>

All fun and games until the structure is a little more complicated, for example consider the following page content:

<div id="myDiv">
    <p>Right-click me</p>
    <div>
       <p>Interesting data</p>
    </div>
</div>

In this case, the code above will not work and return null in this case i’d need to record the myDiv as first parent with an ID and the nodes to reach my wanted interesting data in short a way to pin-point where the data is to be found inside the page. Perhaps my approach is wrong or more complicated than it could be. Imagine I could have an even more intricated content page, with more nested nodes and such.

My next move would be to write an iterator and note down every childIndex in progression until I reach the relevant data but maybe this would not be the correct approach or is there a better, more readable way to write this script?

2

Answers


  1. The event.path property contains an array representing the DOM hierarchy from the target element, up to the root of the document.

    function handleGlobalRightClick(event) {
        // Get the clicked element
        let clickedElement = event.target;
    
        // Find the first parent element with an id
        let parentWithId = event.path.find(element => element.id);
    
        if (parentWithId) {
            console.log(`Parent Id: ${parentWithId.id}`);
    
            // Find the index of the clicked element within its parent
            let childIndex = Array.from(clickedElement.parentElement.children).indexOf(clickedElement);
            console.log(`Child Index: ${childIndex}`);
        }
    }
    
    Login or Signup to reply.
  2. While you traverse up the hierarchy to find the element with the id property (which your code does successfully), also track the child index at each step. This series of indexes can then be used to indicate the path from the id-node to the clicked node.

    Like this (I didn’t bother checking whether the click is a right click):

    function handleGlobalRightClick(event) {
        // Get the clicked element
        let elem = event.target;
        // The path downwards from an element with an id towards the clicked element
        const path = [];
    
        while (elem.parentElement && !elem.id) {
            path.push([].indexOf.call(elem.parentElement.children, elem));
            elem = elem.parentElement;
        }
        path.reverse();
        console.log(`Parent Id: ${elem.id}`);
        console.log(`Child Index/path: ${path.join(" ")}`);
    }
    
    document.addEventListener("click", handleGlobalRightClick);
    div { border: 1px solid; margin: 10px }
    <div id="myDiv">
        <p>If you click here the path is "0" (first child)</p>
        <div>
           <p>if you click here, the path is "1 0"</p>
           <div>
               <p>if you click here, the path is "1 1 0"</p>
           </div>
        </div>
        <div>
           <p>if you click here, the path is "2 0"</p>
           <div>
               <p>if you click here, the path is "2 1 0"</p>
           </div>
        </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search