9

I am trying to alert the correct css selector and xpath on right click on a dom element. I can show a menu on right click but I'm blocked getting the css selector and xpath value. Input for the code will be any website source code (right click on site, view source) or sample html code which has some classnames. I have a reference to pull unique css selector here

Any pointers on how to get unique css selector and xpath on right click on any dom element?

My Fiddle is here

<h2>Copy paste source code</h2>
<textarea id="txtSrcCode"></textarea>
<input type="button" value="Load Page" id="btnLoadPage" />
<div id="divToBindSrcCode">

</div>

<ul class='custom-menu'>
  <li data-action="first">First thing</li>
  <li data-action="second">Second thing</li>
  <li data-action="third">Third thing</li>
</ul>

Jquery code

$('#btnLoadPage').click(function() {
  $('#divToBindSrcCode').html($('#txtSrcCode').val()); // Laod dom on to the page
});

$(document).bind("contextmenu", function(event) {

  // Avoid the real one
  event.preventDefault();
  // Show contextmenu
  $(".custom-menu").finish().toggle(100).

  // In the right position (the mouse)
  css({
    top: event.pageY + "px",
    left: event.pageX + "px"
  });
});


// If the document is clicked somewhere
$(document).bind("mousedown", function(e) {
  // If the clicked element is not the menu
  if (!$(e.target).parents(".custom-menu").length > 0) {
    // Hide it
    $(".custom-menu").hide(100);
  }
});

// If the menu element is clicked
$(".custom-menu li").click(function() {
  var kk = $(this).val();
  // This is the triggered action name
  switch ($(this).attr("data-action")) {
    // A case for each action. Your actions here
    case "first":
      alert(kk);
      break;
    case "second":
      alert("second");
      break;
    case "third":
      alert("third");
      break;
  }

  // Hide it AFTER the action was triggered
  $(".custom-menu").hide(100);
});
daphtdazz
  • 7,754
  • 34
  • 54
Kurkula
  • 6,386
  • 27
  • 127
  • 202
  • 1
    Did you check out [this answer](https://stackoverflow.com/a/15051750/2019247)? – 31piy Jun 01 '17 at 11:37
  • click and right click works differently with $(this) and pulling its parent elements for xpath or css selector. – Kurkula Jun 03 '17 at 21:48

2 Answers2

4

Putting the answer of @jeka5555 together with a library such as css-selector-generator.js, and using MDN's xpath generator you can do this:

<html>
    <head>
        <script src="./css-selector-generator.js"></script>
        <script>
            function getXPathForElement(el, xml) {
                var xpath = '';
                var pos, tempitem2;

                while(el !== xml.documentElement) {
                    pos = 0;
                    tempitem2 = el;
                    while(tempitem2) {
                        if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) { // If it is ELEMENT_NODE of the same name
                            pos += 1;
                        }
                        tempitem2 = tempitem2.previousSibling;
                    }

                    xpath = "*[name()='"+el.nodeName+"' and namespace-uri()='"+(el.namespaceURI===null?'':el.namespaceURI)+"']["+pos+']'+'/'+xpath;

                    el = el.parentNode;
                }
                xpath = '/*'+"[name()='"+xml.documentElement.nodeName+"' and namespace-uri()='"+(el.namespaceURI===null?'':el.namespaceURI)+"']"+'/'+xpath;
                xpath = xpath.replace(/\/$/, '');
                return xpath;
            }
        </script>
        <script>
            function context(event) {
                event.preventDefault();
                console.log(event.target);
                var sel_gen = new CssSelectorGenerator();
                var sel = sel_gen.getSelector(event.target);
                var xpath = getXPathForElement(event.target, document);
                alert("sel: " + sel + "; xpath: " + xpath);
            }
        </script>
    </head>

    <body>
        <div class=myclass>
            <div>
                <p oncontextmenu="context(event)">Right click me</p>
                <p>Clicking me won't help</p>
            </div>
        </div>
    </body>
</html>

This particular case alerts:

sel: .myclass > div > :nth-child(1); xpath: /*[name()='HTML' and namespace-uri()='http://www.w3.org/1999/xhtml']/*[name()='BODY' and namespace-uri()='http://www.w3.org/1999/xhtml'][1]/*[name()='DIV' and namespace-uri()='http://www.w3.org/1999/xhtml'][1]/*[name()='DIV' and namespace-uri()='http://www.w3.org/1999/xhtml'][1]/*[name()='P' and namespace-uri()='http://www.w3.org/1999/xhtml'][1]

I would trust the library to get it right much more than I would trust myself!

And try this jsfiddle.

Also this jsfiddle modifies the Mozilla function to give a simpler xpath.

There are other libraries available for the css selector, see this answer to a similar question.

daphtdazz
  • 7,754
  • 34
  • 54
  • Is this library free to use? In git hub it say unlicensed. – Kurkula Jun 01 '17 at 15:11
  • 1
    It is licensed with the [UNLICENSE license](https://github.com/fczbkk/css-selector-generator/blob/master/UNLICENSE), which says "This is free and unencumbered software released into the public domain.", so yes it's free to use. – daphtdazz Jun 01 '17 at 15:12
  • Sorry for a basic question. Is unique css selector and XPath same? – Kurkula Jun 01 '17 at 15:18
  • 1
    No, because obviously an xpath wouldn't include for example the id or class of an element. But generally with programming HTML / javascript / CSS you only really care about selectors, and xpaths aren't very useful. Do you really need an xpath for something, or just a CSS selector? – daphtdazz Jun 01 '17 at 15:24
  • I am looking for both XPath and css selector as per the question. I am targeting test automation though my script which needs both XPath and css selector. Any addition to your valuable answer would help alot. – Kurkula Jun 01 '17 at 15:26
  • 1
    Updated my answer with the xpath, and also the jsfiddle. – daphtdazz Jun 01 '17 at 15:37
  • 1.) I tried right click on your code in jsfiddle. 2.)I tried right clicking on an element in F12(developer tools/inspect element) and selected copy->xpath. Both results are not the same. Ideally both xpaths should be same. Is it because it is on jsfiddle? – Kurkula Jun 03 '17 at 21:47
  • 1
    It's an equally valid xpath, just completely unambiguous and with the namespace information. It's easy to modify the function to give a simpler path if you want, see http://jsfiddle.net/daphtdazz/8jgyxrbt/ – daphtdazz Jun 04 '17 at 09:55
3

event.target - indicates the element by which you clicked

jeka5555
  • 189
  • 1
  • 15
  • good pointer to get current html element. Any option to get unique css selector please? – Kurkula May 29 '17 at 06:18
  • I would dynamically add to it a unique ID, for example: `var unique = 'id' + (new Date ()). GetTime (); $(event.target).attr('id', unique);` – jeka5555 May 29 '17 at 07:35
  • I mean if there are 4 classes wit same names, I want to get the correct css selector for clicked element. any pointer to get css selector for the clicked element? – Kurkula May 29 '17 at 07:46