简体   繁体   中英

How to track clicks of all the users on buttons on Jira website

I'm trying to pop-up an alert containing the button name whenever the user presses it, not only buttons but also Tags, now the problem is that there's different types of nesting the button content for example it could be like this:

<button>
  <div>
   //content doesn't matter here
  </div>
  <div>
    <span>Button Name </span> I want to display this span inner text
   </div>
</button>

or the button tag could have only one child..etc. Here are the code of three clickable elements:

  • in the first element I want to display "Create Projects" in an alert window:

  • and some buttons have their names as a value of an attribute called aria-label like this:

  • in the first element I want to display "Projects" in an alert window

I wrote the following code, and the problem is sometimes when I press the button the alert shows with the button name, and sometimes it doesn't, here's my code:

// Queue implementation

class Queue
{
    constructor()
    {
        this.items=[];
    }

    // front function 
    front() 
    { 
        // returns the Front element of  
        // the queue without removing it. 
        if(this.isEmpty()) 
            return "No elements in Queue"; 
        return this.items[0]; 
    } 


    enqueue(element)
    {
        this.items.push(element);
    }

    dequeue()
    {
        if (this.isEmpty()) 
            return " Underflow";
        return this.items.shift();
    }

    isEmpty()
    {
        return this.items.length == 0;
    }
}


function BFS(node) {
    let q = new Queue();
    //let explored = new Set();
    q.enqueue(node);
    while (!q.isEmpty()) {
        let currentChild = q.front();   
        q.dequeue()
        let ChildBoy = currentChild.children;
        for (let i = 0 ; i <ChildBoy.length ; i++) {
            q.enqueue(ChildBoy[i]);
            console.log(ChildBoy[i]);
            //explored.add(ChildBoy[i]);
        }


        if (currentChild.textContent != null && currentChild.textContent != undefined && currentChild.textContent != "") 
        {
            alert("textContent"+ "  "+currentChild.textContent);
            break;
        }
        if (currentChild.getAttribute("aria-label") != "" && currentChild.getAttribute("aria-label") != null && currentChild.getAttribute("aria-label") != undefined) 
        {
            alert("aria-label-Content"+"   "+currentChild.getAttribute("aria-label")); 
        }
    }
}

let buttons = document.getElementsByTagName("button");
for (let index = 0; index < buttons.length; index++) {
    let button_i = buttons[index];
    button_i.addEventListener('click', function () {
       BFS(button_i) ;
    });

}



let hrefs = document.getElementsByTagName("a");
for (let index_1 = 0; index_1 < hrefs.length; index_1++) {
    let hrefs_j = hrefs[index_1];
    hrefs_j.addEventListener('click' , function()
    {
        BFS(hrefs_j);
    });

}

and the manifest json file is:

{
    "name" : "first extension",
    "version" : "1.0",
    "description" : "extension for track user",
    "permissions" : [
        "storage",
        "declarativeContent",
        "activeTab"
    ],
    "page_action" : {
        "default_popup" : "popup.html",
        "default_icon": {
            "16": "images/get_started16.png",
            "32": "images/get_started32.png",
            "48": "images/get_started48.png",
            "128": "images/get_started128.png"
          }

    },
    "background" : {
        "scripts" : 
        ["background.js"],
        "persistent" : true
    },
    "icons": {
        "16": "images/get_started16.png",
        "32": "images/get_started32.png",
        "48": "images/get_started48.png",
        "128": "images/get_started128.png"
      },

      "content_scripts" :
      [
          {
            "matches" :["https://*.atlassian.net/*/*" , "https://*.atlassian.com/*" , "https://*.atlassian.net/*"],
            "js" : ["track.js"]
          }
      ],

    "manifest_version" : 2
}

What's the wrong with this code?

The solution does not seem straight forward to me, since you do not know a class or a unique identifier for all visual buttons...

Therefore I will propose one way of doing it.

First add a global click event lister on the document this way you can track all the click and just select what you want.

Something like this, a simple way to see what are you clicking. (maybe you can find a solution just around this)

 document.addEventListener("click", function(event) { const elementType = event.target.tagName; console.log(elementType + ' clicked!'); });
 <div>Test1</div> <span>Test2</span><br> <button>Test3</button><br> <a>Test4</a><br> <button>Test5</button><br> <div> <button>Test6</button> </div> <p>Test7</p>

Then you will have somehow to whitelist what is a button (as you cannot take only the tags)

So for this I was thinking about creating an array or a map (if possible) of XPaths and verify if the clicked element matches with your whitelist. Only then you will get the text.

Note: XPath is a unique path of a node in DOM. That also means you will have to know all XPaths of your buttons.
Usually XPath are not lightweight on terms of performance, but if you run only on click and you find an optimized solution, it should be ok...

Here is an example of what I'm talking about:

 // Using object for performance reasons. const ACCEPTED_XPATHS = { '/html/body/button[1]': 1, '/html/body/button[2]': 1, '/html/body/div[2]/button': 1, '/html/body/div[3]/div/span': 1 } document.addEventListener("click", function(event) { const element = event.target; const elementXPath = xpath(element); // You can use this to collect your accepted list: console.log('CLICKED PATH = ' + elementXPath); if (ACCEPTED_XPATHS[elementXPath]) { console.log('BUTTON CLICKED --- Button Text: ' + element.innerHTML); } }); // https://gist.github.com/iimos/e9e96f036a3c174d0bf4 function xpath(el) { if (typeof el == "string") return document.evaluate(el, document, null, 0, null) if (!el || el.nodeType != 1) return '' if (el.id) return "//*[@id='" + el.id + "']" var sames = [].filter.call(el.parentNode.children, function (x) { return x.tagName == el.tagName }) return xpath(el.parentNode) + '/' + el.tagName.toLowerCase() + (sames.length > 1 ? '['+([].indexOf.call(sames, el)+1)+']' : '') }
 <div>Test1</div> <span>Test2</span><br> <button>Test3</button><br> <a>Test4</a><br> <button>Test5</button><br> <div> <button>Test6</button> </div> <p>Test7</p> <div> <div> <span>THIS IS ALSO A BUTTON</span> </div> </div>

I don't have a better idea right now, Hope it helps :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM