0

It's pretty simple, we have this line. I'd like to grab the info from:

console.log($('#fourth-step tr:nth-child(3) td:nth-child(3)'));

So the output is #fourth-step tr:nth-child(3) td:nth-child(3).

This outputs a very long object but I need only the selector information.

I'm almost sure somewhere already is a thread about this problem but I couldn't find any, sorry.

To make things easier, there is a list of things that I've tried and they didn't work*.

  1. console.log('z' + {obj});
  2. console.log(JSON.stringify({obj}));
  3. console.log(String({obj});

{ and } - shortcut.

Any ideas? :)

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • 1
    This has been asked a lot before and is generally an X/Y question. Instead of storing the selector, store the jQuery object which was created, or dynamically select the elements you require at a later point. If you can explain why you believe you need to do this we will be able to suggest better alternatives. – Rory McCrossan Mar 16 '18 at 16:59
  • You want to use a selector and then, at some point, discover the selector you used? – David Thomas Mar 16 '18 at 16:59
  • @DavidThomas Yea, I need to store that selector info. – Lukas Naujokaitis Mar 16 '18 at 17:01
  • @RoryMcCrossan Thank you for your detailed comment :) I'd like to do that because I'm creating a tic tac toe game and I'd like to know `tr:nth-child()` and `td:nth-child()`value of this selector. Btw, can you explain what is X/Y question, please? – Lukas Naujokaitis Mar 16 '18 at 17:03
  • If you just want the HTML element associated with the selector you can do `$('#fourth-step tr:nth-child(3) td:nth-child(3)').get(0)`, is that what you're wanting? – delinear Mar 16 '18 at 17:04
  • An X/Y question is where you ask about a problem you have with a flawed solution you're trying to create (X) instead of asking about solving the problem you originally had (Y). – Rory McCrossan Mar 16 '18 at 17:04
  • 1
    Also, given those requirements I don't see why you need to store the selectors at all. You can just select the elements when required. – Rory McCrossan Mar 16 '18 at 17:04
  • Storing the jQuery object can have some drawbacks, I have had issues with the objects getting stale, so I have found using a selector to be much more dependable. – Jtbs Mar 16 '18 at 17:06
  • All jQuery objects are stored in the array and from that array, I have to find `nth-child()` values. Based on the values, then I replace it with a different value but that's a different story. – Lukas Naujokaitis Mar 16 '18 at 17:07
  • It's gonna be a Tic Tac Toe BOT. – Lukas Naujokaitis Mar 16 '18 at 17:07
  • @Jtbs What do you mean "getting stale"? What's gonna happen to them over time? And it's also a selector inside an object, so maybe I don't understand you clearly but "using a selector to be much more dependable" sentence makes no sense for me. – Lukas Naujokaitis Mar 16 '18 at 17:09
  • 1
    [Silently LOLing at the ugliness of "abusing" CSS selectors to navigate(?) the DOM of a table in the first place here. The `.rows` and `.cells` collections have existed since DOM Level 1 already ... but hey, today `$ == JavaScript`, am I right kids?] – CBroe Mar 16 '18 at 17:11
  • Maybe my usage was different and doesn't apply, but if you were to get the jQuery object, then modify the dom separately, perhaps adding or removing elements that would show up using the selector, I don't think the jQuery object changes because the selection was done before the change. – Jtbs Mar 16 '18 at 17:15
  • 2
    @CBroe Hehe :D I really didn't know about these two methods. Thank you. `var cell = table.rows[1].cells[1];` seems more simple. – Lukas Naujokaitis Mar 16 '18 at 17:15
  • The hardest part is to get the object's selector as the string. Later I can do everything I want with it. My main purpose is to use `replace()` function to change `nth-child()` values and make it another object with changed position - using `nth-child()`. Maybe there is an easy trick using `cells()` and `rows()` methods? – Lukas Naujokaitis Mar 16 '18 at 17:19
  • 1
    Granted, rather special case here, because you were dealing with a table to begin with, so this of course doesn't translate to many other cases, where using `:nth-child` could make more sense, than trying to navigate through the DOM using this method here, that attribute there ... Plus, browsers these days have highly optimized selector engines, so simply "handing the job over" from pure JS to there makes sense, too. But Tic Tac Toe is such a good example for where using a table makes total sense from the HTML point already, so I couldn't pass the chance to remember some "old DOM friends" ;-) – CBroe Mar 16 '18 at 17:24
  • My game link is here: https://codepen.io/Kestis500/pen/XEKJMX?editors=1010. I'm working on the Player VS Computer mode, that's why I need all your help now :) – Lukas Naujokaitis Mar 16 '18 at 17:26
  • @CBroe Can you say, where using `cells()` and `rows()` makes more sense, or, where `nth-child()` makes more, please? :) – Lukas Naujokaitis Mar 16 '18 at 17:34
  • Well if you just need to get access to cell x in row y to "do something" with it, then I would certainly go for table.rows[y].cells[x] here. Need to set a specific class? `table.rows[y].cells[x].classList.add('foo')` Need to switch out the cell content, to mark a player's choice? `table.rows[y].cells[x].innerHTML='X'` ... what else, any other operations you where trying to locate a specific cell for using nth-child? – CBroe Mar 16 '18 at 17:40
  • @CBroe So I should always use your suggested methods instead of `:nth-child()` if it's not a CSS-Free project, right? :) However, none of the answers answered to my problem, don't know what to do now. – Lukas Naujokaitis Mar 16 '18 at 17:44
  • No, as I said, rather special case here. The table already expresses the "grid" structure of rows and columns of a TTT game quite nicely, and since it also already provides methods to easily locate row y and "column" (cell) x, I'd use them here _in this instance_. _"However, none of the answers answered to my problem, don't know what to do now"_ - well I am not exactly sure what problem you are trying to solve now? The necessity of "caching" any selectors in string form should be gone now, with this easy way to locate any cell at any time? – CBroe Mar 16 '18 at 17:50
  • Yes, maybe, but I'll need to replace this number depending on the user choice so the player will never win against the computer. Can you wait a sec, so I can try to accomplish your suggested method, please? – Lukas Naujokaitis Mar 16 '18 at 17:54
  • Why using your method doesn't work for me? :/ Using non-jquery selector it worked: `document.getElementById('fourth-step').rows[0].cells[0].innerHTML = 'asdasd'; `. https://jsfiddle.net/oerxtgfc/ – Lukas Naujokaitis Mar 16 '18 at 18:00
  • 1
    Because a) you can not just call DOM methods on a jQuery object, you need either `$('#fourth-step')[0].rows...` (shortcut for https://api.jquery.com/get/) or go "fully back to DOM" in the first place, `document.querySelector('#fourth-step').rows...`, and b) the DOM has no `.text()` method either, that's why I mentioned innerHTML: https://jsfiddle.net/oerxtgfc/3/ – CBroe Mar 16 '18 at 18:04
  • I've done everything how you said and it worked, however, I still can't access my selector. Now I don't get a big object, instead, I just got an element ``. How to access information where is it's place in the table? https://jsfiddle.net/fd4hv4tx/ – Lukas Naujokaitis Mar 16 '18 at 18:40
  • If nobody will answer this question, I'm just going to use basic `#id` stuff and it won't bother me so much :D Maybe that's the solution. – Lukas Naujokaitis Mar 16 '18 at 18:57
  • _"How to access information where is it's place in the table?"_ - what do you mean by "place in the table"? Don't say the "coordinates", as in x/y, as in those two values you just used to _get_ the reference to the table cell object ...? – CBroe Mar 16 '18 at 19:11
  • I mean how to get the value of method `cells[...]` or `rows[...]` after they were executed for later use? How to get these numbers? E.g. if `...` was `2`, then, how to get 2 later associated with this element? – Lukas Naujokaitis Mar 16 '18 at 19:23
  • I'll use class name of `field`, so it's going to be very straightforward but I'm just curious about these two methods you provided recently :) – Lukas Naujokaitis Mar 16 '18 at 19:24
  • 1
    Just go read up a little on what DOM properties there are for different types of elements. For example, there's https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableRowElement/rowIndex and a corresponding HTMLTableCellElement.cellIndex, so if `var specialCell = tableElement.rows[5].cells[2]`, then go check what `specialCell.cellIndex` contains afterwards. (row index is _on_ the row element, so one level up - `specialCell.parentNode.rowIndex`) – CBroe Mar 16 '18 at 19:30

2 Answers2

0

jQuery has the .selector() method but is deprecated since it doesn't return - at times - the desired result. Try out this jQuery plugin that I've written to get a more unique CSS selector:

$.fn.extend({
  getSelector: function() {
    var path = [],
      currentElement = this[0];

    while (currentElement.nodeName.toLowerCase() != 'html') {
      var selector = currentElement.nodeName.toLowerCase();

      if (currentElement.id)
        selector += '#' + currentElement.id;

      if (!currentElement.id && currentElement.className)
        selector += '.' + currentElement.className;

      path.push(selector);

      currentElement = currentElement.parentNode;
    }

    return path.reverse().join(' > ');
  }
});

Check out this git repo: jQuery Plugins Library

baeyun
  • 228
  • 1
  • 6
0

Until jQuery 1.7, there was selector property, but it's now deprecated. The best you can do is to store the selector as a property of the element, like this:

$(selector).data('selector',selector)

Note that after moving or cloning your element around in the page, the selector may not match anymore the element. This may be the reason behind the deprecation of selector property.

See also here

Mario Cianciolo
  • 1,223
  • 10
  • 17