0

I am creating a Chrome Extension similar to the "Search on Google" when you right click on a selected text. However, I need mine to also work when right clicking on a mailto: e-mail link. How can I select the innerHTML, to select the e-mail address, and pass this information onto the extension to be searched?

I managed to make it work with the selected text (when highlighting text on the website) and right-clicking, but not when right-clicking on a hyperlinked e-mail address.

for(var i=0; i<numentries; i++)
 {
  //alert(_all[i][3]);
  if(_all[i][3])
  {
   _all[i][0] = chrome.contextMenus.create({"title": _all[i][1], "contexts":["selection", "link"], "onclick": searchOnClick});
   //alert("Menuitem created");
  }
  else _all[i][0] = -1;
 }

 var ask_options = getItem("_askoptions")=="true"? true : false;

 if(ask_options){
  //show separator
  chrome.contextMenus.create({"type": "separator", "contexts":["selection", "link"]});
  //show the item for linking to extension options
  chrome.contextMenus.create({"title": "Options", "contexts":["selection", "link"], "onclick": function(){chrome.tabs.create({"url":"options.html"});}});
 }
}

function searchOnClick(info, tab)
{
 var itemindex = 0;
 for(var i=0; i<numentries; i++)
 {
  if(info.menuItemId == _all[i][0])
  {
   //alert(i);
   itemindex = i;
  }
 }
 var ask_fg = getItem("_askbg")=="true"? false : true;
 var ask_next = getItem("_asknext")=="true"? true : false;
 var index = 1000;

 var targetURL = _all[itemindex][2].replace("TESTSEARCH", info.selectionText);
 targetURL = targetURL.replace("%s", info.selectionText);

Right now, it's only searching for the selection. When I attempt to search for a e-mail address hyperlink, the searched word is "undefined".

I need to change "undefined" to the e-mail address in the hyperlink.

Here is what I need to happen: https://i.stack.imgur.com/0OANN.png

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Daniel
  • 3
  • 1
  • Hey again guys... I've been having a very hard time getting this together. I'm a total newbie with 1% coding experience. I've asked 2 developers to try and get this done for me, as I really need it for work, and both failed. Is there a place I can share the entire code to get assistance on this? – Daniel Apr 13 '19 at 20:08

2 Answers2

0

I'm not sure about some of the Chrome-extension-specific stuff (and your snippet is giving an error that I had trouble debugging without your HTML markup), but I think this script will demonstrate how to do what you want.

Edit:
You did indeed say you wanted to know how to run the script in response to a right-click, but I omitted that part. Sorry about that. The revised version should clarify that. It logs the innerHTML of the clicked element (although not on left-clicks) if the element is an anchor whose href attribute starts with mailto:.

// Run the 'checkAnchorForEmail' function on non-primary click events
document.addEventListener("auxclick", checkAnchorForEmail);

function checkAnchorForEmail(event){ //'event' will be our local name for any event that triggers this function
  // Refer to the event's target element as 'clickedElement' 
  let clickedElement = event.target;
  // If the element was an anchor with an 'href' attribute...
  if(clickedElement.tagName.toLowerCase() === "a" &&  clickedElement.href){
    // Define a string to identify anchors with emails
    let comparedString = "mailto:";
    // Only respond if the href begins with that particular string
    if(clickedElement.href.indexOf(comparedString) === 0){
      // Now we know the user right-clicked* an `a` element with an email address and can act accordingly
    console.log(clickedElement.innerHTML);
    }
  }
}

// *Note that the 'auxclick' event is triggered by any non-primary button click. To isolate right-clicks, the 'contextmenu' event may be useful.
<a href="mailto:test@google.com">test@google.com</a><br />
<a href="docs.google.com">google docs</a><br />
<a href="mailto:test2@google.com">test2@google.com</a>

One other thing:
If you need to prevent the context menu from appearing until your script has completed its tasks, you can use event.preventDefault();, but then you would need to show the menu manually later. One way to do this is by firing the 'contextmenu' event on the target element.

It's possible that doing so would cause this script to run again, creating an infinite loop. If this happens, you might try calling the preventDefault method conditionally like this (untested):

function checkAnchorForEmail(event){
  // The above code goes here...
    // Now we know the user right-clicked* an `a` element with an email address and can act accordingly
    if(event.target.dataset.ready != "true"){ // Check the data-ready attribute
      // event.preventDefault();
      // event.target.dataset.ready = "true" // Set the data-ready attribute
      // Make your changes to the context menu here
    }
    else{
      // The changes have already been made, so show the context menu here
      // (maybe using a technique like the one in the link below)
    }
  }

Here is a suggestion for using the MouseEvent interface to open the context menu, as mentioned in the in-code comments.

Cat
  • 4,141
  • 2
  • 10
  • 18
  • Hey Cat. I'm not sure how to implement that but I will give it a try. Thanks. – Daniel Apr 09 '19 at 20:21
  • I updated the answer to deal with responding to right-clicks, as you originally asked, and I added a note about delaying the appearance of the context menu if necessary (and preventing an infinite loop while doing so.) – Cat Apr 12 '19 at 11:25
0

You need to add an event listener for the contextmenu.

Using the example cat gave, I created a quick jsfiddle: https://jsfiddle.net/kds2Lze8/

The code below adds the event listener to the document and is triggered on right click. Using that event you can then get the source element and ultimately the innerHTML.

Hope it helps!

document.addEventListener('contextmenu', function(ev) {
    ev.preventDefault();
    alert(ev.srcElement.innerHTML);
    return false;
}, false);
TheTechy
  • 172
  • 2
  • 13