How to get css selector for an element using javascript? - javascript

Is there any jQuery plugin or javascript code that returns a CSS-selector that uniquely selects a particular element?
I'm looking for something with similar functionality as provided by the Copy CSS Path function in Chrome's developer tools, giving me a selector that looks something like this:
#question > table > tbody > tr:nth-child(2) > td > div > h2
Answers I tried
Get unique selector of element in Jquery
Get unique selector jQuery

Just found this post, had a look at the only answer and got terrified by it's complexity and by bizarre denial from using jQuery functions. Sorry for criticism, but i really i got stunned by this callback system. Here, have it in easy to use form:
function getCSSPath(el) {
let rendered_path_parts = [];
$( el ).parents().addBack().each((i, el) => {
const $el = $( el );
let current_el_path = $el.prop('tagName').toLowerCase();
if ($el.attr('id')) {
current_el_path += '#' + $el.attr('id');
}
if ($el.attr('class')) {
current_el_path += '.' + $el.attr('class').split(' ').join('.');
}
rendered_path_parts.push( current_el_path );
})
return rendered_path_parts.join(' ');
}
$.fn.extend({
getPath: function() {
return getCSSPath(this.length === 1 ? this : this.eq(0));
}
});
getCSSPath(some_element);
some_jquery_element.getPath();
Note that rendered selector will not include element' index, so it is less descriptive than selector developer tools can make for you.

Not perfect, but written fast (for You) : )
http://jsfiddle.net/k1qs69fz/7/
Code:
function getCSSPath(el, callback){
var fullPath = '';
var cssPathFn = function (el, callback){
var elPath = '';
elPath = $(el).prop('tagName').toLowerCase();
if(typeof $(el).attr('id') !== 'undefined'){
elPath = elPath+'#'+$(el).attr('id');
}
if(typeof $(el).attr('class') !== 'undefined'){
elPath = elPath+'.'+$(el).attr('class').split(' ').join('.');
}
fullPath = elPath+' '+fullPath;
if(typeof $(el).parent().prop('tagName') !== 'undefined'){
cssPathFn($(el).parent(), callback);
}
else{
callback(fullPath);
}
};
cssPathFn(el, callback);
}
Usage:
getCSSPath($('selector'), callbackFunction);
Function is based on tag name, id and class names, indexes are not supported.
Sample usage (for HTML code on JSFiddle):
$(document).ready(function (){
getCSSPath($('#lorem-ipsum'), function (path){
console.log(path);
});
});
Sample Result:
html body div#id1.c1.c2.c3 div#id2 div.c4.c5 span span.c6 ul li a span#lorem-ipsum

Here is a pure JavaScript implementation of what the others had using Element.attributes so it should work everywhere.
I made it a snippet so you can see that document.querySelector works with the selector found.
function getCSSSelector(el){
let selector = el.tagName.toLowerCase();
const attrs = el.attributes
for (var i = 0; i < attrs.length; i++) {
let attr = attrs.item(i)
if (attr.name === 'id') selector += `#${attr.value}`;
if (attr.name === 'class') selector += attr.value.split(' ').map((c) => `.${c}`).join('');
if (attr.name === 'name') selector += `[${attr.name}=${attr.value}]`;
}
return selector
}
let el = document.querySelector('input#id.abc');
let selector = getCSSSelector(el);
console.log(selector)
document.querySelector(selector).value = selector;
<input id="id", class="abc def" name='name' style='width: 200px'>

Related

How to get the string passed to jquery? [duplicate]

$("*").click(function(){
$(this); // how can I get selector from $(this) ?
});
Is there an easy way to get selector from $(this)? There is a way to select an element by its selector, but what about getting the selector from element?
Ok, so in a comment above the question asker Fidilip said that what he/she's really after is to get the path to the current element.
Here's a script that will "climb" the DOM ancestor tree and then build fairly specific selector including any id or class attributes on the item clicked.
See it working on jsFiddle: http://jsfiddle.net/Jkj2n/209/
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
$(function() {
$("*").on("click", function(e) {
e.preventDefault();
var selector = $(this)
.parents()
.map(function() { return this.tagName; })
.get()
.reverse()
.concat([this.nodeName])
.join(">");
var id = $(this).attr("id");
if (id) {
selector += "#"+ id;
}
var classNames = $(this).attr("class");
if (classNames) {
selector += "." + $.trim(classNames).replace(/\s/gi, ".");
}
alert(selector);
});
});
</script>
</head>
<body>
<h1><span>I love</span> jQuery</h1>
<div>
<p>It's the <strong>BEST THING</strong> ever</p>
<button id="myButton">Button test</button>
</div>
<ul>
<li>Item one
<ul>
<li id="sub2" >Sub one</li>
<li id="sub2" class="subitem otherclass">Sub two</li>
</ul>
</li>
</ul>
</body>
</html>
For example, if you were to click the 2nd list nested list item in the HTML below, you would get the following result:
HTML>BODY>UL>LI>UL>LI#sub2.subitem.otherclass
::WARNING:: .selector has been deprecated as of version 1.7, removed as of 1.9
The jQuery object has a selector property I saw when digging in its code yesterday. Don't know if it's defined in the docs are how reliable it is (for future proofing). But it works!
$('*').selector // returns *
Edit: If you were to find the selector inside the event, that information should ideally be part of the event itself and not the element because an element could have multiple click events assigned through various selectors. A solution would be to use a wrapper to around bind(), click() etc. to add events instead of adding it directly.
jQuery.fn.addEvent = function(type, handler) {
this.bind(type, {'selector': this.selector}, handler);
};
The selector is being passed as an object's property named selector. Access it as event.data.selector.
Let's try it on some markup (http://jsfiddle.net/DFh7z/):
<p class='info'>some text and <a>a link</a></p>​
$('p a').addEvent('click', function(event) {
alert(event.data.selector); // p a
});
Disclaimer: Remember that just as with live() events, the selector property may be invalid if DOM traversal methods are used.
<div><a>a link</a></div>
The code below will NOT work, as live relies on the selector property
which in this case is a.parent() - an invalid selector.
$('a').parent().live(function() { alert('something'); });
Our addEvent method will fire, but you too will see the wrong selector - a.parent().
In collaboration with #drzaus we've come up with the following jQuery plugin.
jQuery.getSelector
!(function ($, undefined) {
/// adapted http://jsfiddle.net/drzaus/Hgjfh/5/
var get_selector = function (element) {
var pieces = [];
for (; element && element.tagName !== undefined; element = element.parentNode) {
if (element.className) {
var classes = element.className.split(' ');
for (var i in classes) {
if (classes.hasOwnProperty(i) && classes[i]) {
pieces.unshift(classes[i]);
pieces.unshift('.');
}
}
}
if (element.id && !/\s/.test(element.id)) {
pieces.unshift(element.id);
pieces.unshift('#');
}
pieces.unshift(element.tagName);
pieces.unshift(' > ');
}
return pieces.slice(1).join('');
};
$.fn.getSelector = function (only_one) {
if (true === only_one) {
return get_selector(this[0]);
} else {
return $.map(this, function (el) {
return get_selector(el);
});
}
};
})(window.jQuery);
Minified Javascript
// http://stackoverflow.com/questions/2420970/how-can-i-get-selector-from-jquery-object/15623322#15623322
!function(e,t){var n=function(e){var n=[];for(;e&&e.tagName!==t;e=e.parentNode){if(e.className){var r=e.className.split(" ");for(var i in r){if(r.hasOwnProperty(i)&&r[i]){n.unshift(r[i]);n.unshift(".")}}}if(e.id&&!/\s/.test(e.id)){n.unshift(e.id);n.unshift("#")}n.unshift(e.tagName);n.unshift(" > ")}return n.slice(1).join("")};e.fn.getSelector=function(t){if(true===t){return n(this[0])}else{return e.map(this,function(e){return n(e)})}}}(window.jQuery)
Usage and Gotchas
<html>
<head>...</head>
<body>
<div id="sidebar">
<ul>
<li>
Home
</li>
</ul>
</div>
<div id="main">
<h1 id="title">Welcome</h1>
</div>
<script type="text/javascript">
// Simple use case
$('#main').getSelector(); // => 'HTML > BODY > DIV#main'
// If there are multiple matches then an array will be returned
$('body > div').getSelector(); // => ['HTML > BODY > DIV#main', 'HTML > BODY > DIV#sidebar']
// Passing true to the method will cause it to return the selector for the first match
$('body > div').getSelector(true); // => 'HTML > BODY > DIV#main'
</script>
</body>
</html>
Fiddle w/ QUnit tests
http://jsfiddle.net/CALY5/5/
Did you try this ?
$("*").click(function(){
$(this).attr("id");
});
Try this:
$("*").click(function(event){
console.log($(event.handleObj.selector));
});
Well, I wrote this simple jQuery plugin.
This checkes id or class name, and try to give as much exact selector as possible.
jQuery.fn.getSelector = function() {
if ($(this).attr('id')) {
return '#' + $(this).attr('id');
}
if ($(this).prop("tagName").toLowerCase() == 'body') return 'body';
var myOwn = $(this).attr('class');
if (!myOwn) {
myOwn = '>' + $(this).prop("tagName");
} else {
myOwn = '.' + myOwn.split(' ').join('.');
}
return $(this).parent().getSelector() + ' ' + myOwn;
}
Just add a layer over the $ function this way:
$ = (function(jQ) {
return (function() {
var fnc = jQ.apply(this,arguments);
fnc.selector = (arguments.length>0)?arguments[0]:null;
return fnc;
});
})($);
Now you can do things like $("a").selector and will return "a" even on newer jQuery versions.
http://www.selectorgadget.com/ is a bookmarklet designed explicitly for this use case.
That said, I agree with most other people in that you should just learn CSS selectors yourself, trying to generate them with code is not sustainable. :)
I added some fixes to #jessegavin's fix.
This will return right away if there is an ID on the element. I also added a name attribute check and a nth-child selector in case a element has no id, class, or name.
The name might need scoping in case there a multiple forms on the page and have similar inputs, but I didn't handle that yet.
function getSelector(el){
var $el = $(el);
var id = $el.attr("id");
if (id) { //"should" only be one of these if theres an ID
return "#"+ id;
}
var selector = $el.parents()
.map(function() { return this.tagName; })
.get().reverse().join(" ");
if (selector) {
selector += " "+ $el[0].nodeName;
}
var classNames = $el.attr("class");
if (classNames) {
selector += "." + $.trim(classNames).replace(/\s/gi, ".");
}
var name = $el.attr('name');
if (name) {
selector += "[name='" + name + "']";
}
if (!name){
var index = $el.index();
if (index) {
index = index + 1;
selector += ":nth-child(" + index + ")";
}
}
return selector;
}
I've released a jQuery plugin: jQuery Selectorator, you can get selector like this.
$("*").on("click", function(){
alert($(this).getSelector().join("\n"));
return false;
});
I was getting multiple elements even after above solutions, so i extended dds1024 work, for even more pin-pointing dom element.
e.g. DIV:nth-child(1) DIV:nth-child(3) DIV:nth-child(1) ARTICLE:nth-child(1) DIV:nth-child(1) DIV:nth-child(8) DIV:nth-child(2) DIV:nth-child(1) DIV:nth-child(2) DIV:nth-child(1) H4:nth-child(2)
Code:
function getSelector(el)
{
var $el = jQuery(el);
var selector = $el.parents(":not(html,body)")
.map(function() {
var i = jQuery(this).index();
i_str = '';
if (typeof i != 'undefined')
{
i = i + 1;
i_str += ":nth-child(" + i + ")";
}
return this.tagName + i_str;
})
.get().reverse().join(" ");
if (selector) {
selector += " "+ $el[0].nodeName;
}
var index = $el.index();
if (typeof index != 'undefined') {
index = index + 1;
selector += ":nth-child(" + index + ")";
}
return selector;
}
Taking in account some answers read here I'd like to propose this:
function getSelectorFromElement($el) {
if (!$el || !$el.length) {
return ;
}
function _getChildSelector(index) {
if (typeof index === 'undefined') {
return '';
}
index = index + 1;
return ':nth-child(' + index + ')';
}
function _getIdAndClassNames($el) {
var selector = '';
// attach id if exists
var elId = $el.attr('id');
if(elId){
selector += '#' + elId;
}
// attach class names if exists
var classNames = $el.attr('class');
if(classNames){
selector += '.' + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, '.');
}
return selector;
}
// get all parents siblings index and element's tag name,
// except html and body elements
var selector = $el.parents(':not(html,body)')
.map(function() {
var parentIndex = $(this).index();
return this.tagName + _getChildSelector(parentIndex);
})
.get()
.reverse()
.join(' ');
if (selector) {
// get node name from the element itself
selector += ' ' + $el[0].nodeName +
// get child selector from element ifself
_getChildSelector($el.index());
}
selector += _getIdAndClassNames($el);
return selector;
}
Maybe useful to create a jQuery plugin?
This can get you selector path of clicked HTML element-
$("*").on("click", function() {
let selectorPath = $(this).parents().map(function () {return this.tagName;}).get().reverse().join("->");
alert(selectorPath);
return false;
});
Are you trying to get the name of the current tag that was clicked?
If so, do this..
$("*").click(function(){
alert($(this)[0].nodeName);
});
You can't really get the "selector", the "selector" in your case is *.
Javascript code for the same, in case any one needs, as i needed it. This just the translation only of the above selected answer.
<script type="text/javascript">
function getAllParents(element){
var a = element;
var els = [];
while (a && a.nodeName != "#document") {
els.unshift(a.nodeName);
a = a.parentNode;
}
return els.join(" ");
}
function getJquerySelector(element){
var selector = getAllParents(element);
/* if(selector){
selector += " " + element.nodeName;
} */
var id = element.getAttribute("id");
if(id){
selector += "#" + id;
}
var classNames = element.getAttribute("class");
if(classNames){
selector += "." + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, ".");
}
console.log(selector);
alert(selector);
return selector;
}
</script>
Thank you p1nox!
My problem was to put focus back on an ajax call that was modifying part of the form.
$.ajax({ url : "ajax_invite_load.php",
async : true,
type : 'POST',
data : ...
dataType : 'html',
success : function(html, statut) {
var focus = $(document.activeElement).getSelector();
$td_left.html(html);
$(focus).focus();
}
});
I just needed to encapsulate your function in a jQuery plugin:
!(function ($, undefined) {
$.fn.getSelector = function () {
if (!this || !this.length) {
return ;
}
function _getChildSelector(index) {
if (typeof index === 'undefined') {
return '';
}
index = index + 1;
return ':nth-child(' + index + ')';
}
function _getIdAndClassNames($el) {
var selector = '';
// attach id if exists
var elId = $el.attr('id');
if(elId){
selector += '#' + elId;
}
// attach class names if exists
var classNames = $el.attr('class');
if(classNames){
selector += '.' + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, '.');
}
return selector;
}
// get all parents siblings index and element's tag name,
// except html and body elements
var selector = this.parents(':not(html,body)')
.map(function() {
var parentIndex = $(this).index();
return this.tagName + _getChildSelector(parentIndex);
})
.get()
.reverse()
.join(' ');
if (selector) {
// get node name from the element itself
selector += ' ' + this[0].nodeName +
// get child selector from element ifself
_getChildSelector(this.index());
}
selector += _getIdAndClassNames(this);
return selector;
}
})(window.jQuery);
This won't show you the DOM path, but it will output a string representation of what you see in eg chrome debugger, when viewing an object.
$('.mybtn').click( function(event){
console.log("%s", this); // output: "button.mybtn"
});
https://developer.chrome.com/devtools/docs/console-api#consolelogobject-object
How about:
var selector = "*"
$(selector).click(function() {
alert(selector);
});
I don't believe jQuery store the selector text that was used. After all, how would that work if you did something like this:
$("div").find("a").click(function() {
// what would expect the 'selector' to be here?
});
The best answer would be
var selector = '#something';
$(selector).anything(function(){
console.log(selector);
});

How to get all the src and href attributes of a web site

I want a way to get all the src and href attributes(like images and links) in a website. How can i make this in javascript?
I try this:
var ilist=document.links;
for(var i = 0; i < ilist.length; i++) {
if(ilist[i].href) {
alert(ilist[i].href)
}
}
But for a something, this not works. Only works for . I want all href's and all src's for all tags. Can anybody help me?
Using plain JS you can do:
The string that we give querySelectorAll is just a normal CSS selector.
var srcNodeList = document.querySelectorAll('[src],[href]');
for (var i = 0; i < srcNodeList.length; ++i) {
var item = srcNodeList[i];
if(item.getAttribute('src') !== null){
alert(item.getAttribute('src'));
}
if(item.getAttribute('href') !== null){
alert(item.getAttribute('href'));
}
}
Here's the fiddle: https://jsfiddle.net/vpbepvco/1/
Using jquery you can run each on all elements with the all selector
$( "*" ).each(function() {
$(this).attr("src");
});
Use jQuery, but you have to take care about performance.
$("[src],[href]").each(function(){
var $el = $(this);
if( $el.is("a") ) {
// do some stuff with A element
} else if( $el.is("img") ) {
// do some stuff with A element
}
});

Regular Expression that doesn't match html tags in javascript [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
highlight words in html using regex & javascript - almost there
UPDATE --> The final script, once resolved, is, that one:
var regex;
var filterSize;
function normalizar(str) {
var fin=str.toLowerCase().replace('á','a').replace('é','e').replace('í','i').replace('ó','o').replace('ú','u');
return fin;
}
function highlight(fin) {
htmlFin="";
while ((match = regex.exec(normalizar(fin))) != null) {
posIni=match.index;
posEnd = posIni+filterSize;
var ini="";
if (posIni != 0) ini=fin.substring(0, posIni);
var sub=fin.substring(posIni, posEnd);
fin=fin.substring(posEnd, fin.length);
htmlFin += ini+"<span class='highlight'>"+sub+"</span>";
}
htmlFin += fin;
return htmlFin;
}
function procesar(elemento) {
elemento.children().each(function() {
var mas=$(this).children().size();
if (mas == 0) {
$(this).html(highlight($(this).text()));
} else {
procesar($(this));
}
});
}
$(document).ready(function(){
$(".filter").keyup(function(){
// Cogemos el texto de búsqueda
var filter = $(this).val();
//Ponemos el contador a 0
var count = 0;
$('span.highlight').each(function() {
$(this).replaceWith($(this).text());
});
//Por cada elemento de la lista...
$(".list tr:not(:first-child)").each(function(){
var html=$(this).html();
var posIni = -1;
var posEnd = -1;
filterNorm=normalizar(filter);
filterSize=filter.length;
regex=new RegExp(filterNorm, 'gi');
var buscar=normalizar($(this).text()).search(regex);
var htmlFin="";
if (buscar > -1) {
if (filter) procesar($(this));
$(this).show();
count++;
} else $(this).fadeOut();
});
// Actualizamos la cuenta
if (filter) {
var numberItems = count;
//Si no hay coincidencias lo mostramos en rojo.
if (count==0) $(".cuenta").html("<span class='error'>Coincidencias = "+count+"</span>");
else $(".cuenta").text("Coincidencias: "+count);
//Si no hay filtro, limpiamos el html de cuentas.
} else $(".cuenta").text("");
});
});
The goal to make a search script with jquery/javascript that highlight the matches within a from an input. It must ignore case and diacritics (accents) signs and html tags
I'm so close to do it, but It fails cause it doesn't ignore html tags, I mean, the script highlight html tags matches as well...
For example:
UPDATE: You can try the script here jsfiddle.net/josecash/nD6dg/2, just type td or < or > to see the error.
Lets say I have a table like this:
<table>
<tr><th>Name</th><th>Kind</th><th>Type</th></tr>
<tr>
<td><strong>Fedora</strong></td>
<td>Linux</td>
<td>Operative System</td>
</tr>
</table>
If I type the letter o in the input, my script will highlight the o in Fedora, and in Operating System, but also the o in the tag strong.
I suppose I can do that with a regular expression in the regex var, but I can't figure it out...
Any help would be really appreciate
The script looks like this:
$(document).ready(function(){
$(".filter").keyup(function(){
// Input text
var filter = $(this).val();
//Ponemos el contador a 0
var count = 0;
$('span.highlight').each(function() {
$(this).replaceWith($(this).text());
});
//Foreach tr in the table
$(".list tr:not(:first-child)").each(function(){
var html=$(this).html();
var posIni = -1;
var posEnd = -1;
// normalizar just replace accents
filterNorm=normalizar(filter);
var filterSize=filter.length;
var regex=new RegExp(filterNorm, 'gi');
var buscar=normalizar($(this).text()).search(regex);
var htmlFin="";
if (buscar > -1) {
if (filter) {
var end=html;
while ((match = regex.exec(normalizar(end))) != null) {
posIni=match.index;
posEnd = posIni+filterSize;
var ini="";
if (posIni != 0) ini=end.substring(0, posIni);
var sub=end.substring(posIni, posEnd);
end=end.substring(posEnd, end.length);
htmlFin += ini+"<span class='highlight'>"+sub+"</span>";
}
htmlFin += end;
}
if (filter) $(this).show().html(htmlFin);
else $(this).show();
count++;
} else $(this).fadeOut();
});
});
});
#Josecash,
A good way to avoid handling the HTML markup itself is to :
discover child nodes with plain javascript rather than jQuery
treat text nodes as they are encountered
penetrate further into element nodes (recursively) as they are encountered.
The overall code will be something like this :
$(document).ready(function(){
//Highlighter function
function highlight(text) {
//Your highlight code here
//...
//return text with added HTML markup
}
//Recursive scanner function to penetrate the DOM tree.
function scanNode(index, node) {
//node is a plain javascript reference to a DOM node, not jQuery-wrapped.
if(node.nodeType == 3) {//hurray, it's a TEXT_NODE
$(node).replaceWith(highlight(node.nodeValue));
}
else if(node.nodeType == 1){//it's an ELEMENT_NODE
//Here, for convenience, we use jQuery's utility `.each() method
//but we are still essentially working in plain javascript.
$.each(node.childNodes, scanNode);
}
}
var $list = $(".list");
//master routine
$(".filter").keyup(function() {
$list.find('span.highlight').each(function() {
var $this = $(this);
$this.replaceWith($this.text());
}).find("tr:gt(1)").each(scanNode);
});
});
With thanks to #Bergi for his input below
You will have to write the highlight() function, which will be a fairly light modification of the code you posed above. Make sure the function returns the marked up text string.
The critical line $(node).replaceWith(highlight(node.nodeValue)); has been tested (in Opera 12.12 and IE9); jsFiddle
Everything else is untested so may need debugging.
You shouldn't use 'html' as your regex testing string, use the resulting text instead.
Test following code:
if (filter) {
//replace this line:: var end=html; by
var end= $(this).text();
....
}

Add multiple items to text-area with duplicate items

Add multiple items to text-area with duplicate items.
I have one text-area which store data after clicked add data link.
How can i prevent add duplicate items to text-area?
JavaScript call DOM event:
var Dom = {
get: function(el) {
if (typeof el === 'string') {
return document.getElementById(el);
} else {
return el;
}
},
add: function(el, dest) {
var el = this.get(el);
var dest = this.get(dest);
dest.appendChild(el);
},
remove: function(el) {
var el = this.get(el);
el.parentNode.removeChild(el);
}
};
var Event = {
add: function() {
if (window.addEventListener) {
return function(el, type, fn) {
Dom.get(el).addEventListener(type, fn, false);
};
} else if (window.attachEvent) {
return function(el, type, fn) {
var f = function() {
fn.call(Dom.get(el), window.event);
};
Dom.get(el).attachEvent('on' + type, f);
};
}
}()
};
JQuery add data to textarea:
$("#lkaddlanguage").click(function(){
var totalstring;
var checkconstring = $("#contentlng").text();
var strLen = checkconstring.length;
myStr = checkconstring.slice(0,strLen-1);
//alert(myStr);
var checkedItemsArray = myStr.split(";");
var j = 0;
var checkdup=0;
totalstring=escape($("#textval").val()) ;
var i = 0;
var el = document.createElement('b');
el.innerHTML = totalstring +";";
Dom.add(el, 'txtdisplayval');
Event.add(el, 'click', function(e) {
Dom.remove(this);
});
});
HTML Display data
<input type="textbox" id="textval">
<a href="#lnk" id="lkaddlanguage" >Add Data</a>
<textarea readonly id="txtdisplayval" ></textarea>
This seems a very straightforward requirement to me, so I'm not quite clear where you're getting stuck. I have not tried too hard to figure out your existing code given that you are referencing elements not shown in your html ("contentlng"). Also, mixing your own DOM code with jQuery seems a bit pointless. You don't need jQuery at all, but having chosen to include it why then deliberate not use it?
Anyway, the following short function will keep a list of current items (using a JS object) and check each new item against that list. Double-clicking an item will remove it. I've put this in a document ready, but you can manage that as you see fit:
<script>
$(document).ready(function() {
var items = {};
$("#lkaddlanguage").click(function(){
var currentItem = $("#textval").val();
if (currentItem === "") {
alert("Please enter a value.");
} else if (items[currentItem]) {
alert("Value already exists.");
} else {
items[currentItem] = true;
$("#txtdisplayval").append("<span>" + currentItem + "; </span>");
}
// optionally set up for entry of next value:
$("#textval").val("").focus();
return false;
});
$("#txtdisplayval").on("dblclick", "span", function() {
delete items[this.innerHTML.split(";")[0]];
$(this).remove();
});
});
</script>
<input type="textbox" id="textval">
<a href="#lnk" id="lkaddlanguage" >Add Data</a><br>
<div id="txtdisplayval" ></div>
<style>
#txtdisplayval {
margin-top: 5px;
width : 200px;
height : 100px;
overflow-y : auto;
border : 1px solid black;
}
</style>
Note I'm using a div (styled to have a border and allow vertical scrolling) instead of a textarea.
As you can see I've coded it to display an alert for duplicate or empty items, but obviously you could remove that and just ignore duplicates (or substitute your own error handling). Also I thought it might be handy to clear the entry field and set focus back to it ready for entry of the next value, but of course you can remove that too.
Working demo: http://jsfiddle.net/LTsBR/1/
I'm confused.
The only variable that might have duplicates comes from:
var checkedItemsArray = myStr.split(";");
However, checkedItemsArray is not used for anything.
Incidentally, the escape method is deprecated in favour of encodeURIComopnent.
When setting the value of the textarea, do just that: assign to its value property, not to its innerHTML (it can't have markup inside it or any elements, only text nodes).
If you want to check that the members of checkedItemsArray are unique, and you don't mind if they are sorted, you can use a simple function like:
function unique(arr) {
arr.sort();
var i = arr.length;
while (i--) {
if (arr[i] == arr[i - 1]) {
arr.splice(i, 1);
}
}
return arr;
}
Orignal order can be maintained, but it's a bit more code.

How can I get selector from jQuery object

$("*").click(function(){
$(this); // how can I get selector from $(this) ?
});
Is there an easy way to get selector from $(this)? There is a way to select an element by its selector, but what about getting the selector from element?
Ok, so in a comment above the question asker Fidilip said that what he/she's really after is to get the path to the current element.
Here's a script that will "climb" the DOM ancestor tree and then build fairly specific selector including any id or class attributes on the item clicked.
See it working on jsFiddle: http://jsfiddle.net/Jkj2n/209/
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
$(function() {
$("*").on("click", function(e) {
e.preventDefault();
var selector = $(this)
.parents()
.map(function() { return this.tagName; })
.get()
.reverse()
.concat([this.nodeName])
.join(">");
var id = $(this).attr("id");
if (id) {
selector += "#"+ id;
}
var classNames = $(this).attr("class");
if (classNames) {
selector += "." + $.trim(classNames).replace(/\s/gi, ".");
}
alert(selector);
});
});
</script>
</head>
<body>
<h1><span>I love</span> jQuery</h1>
<div>
<p>It's the <strong>BEST THING</strong> ever</p>
<button id="myButton">Button test</button>
</div>
<ul>
<li>Item one
<ul>
<li id="sub2" >Sub one</li>
<li id="sub2" class="subitem otherclass">Sub two</li>
</ul>
</li>
</ul>
</body>
</html>
For example, if you were to click the 2nd list nested list item in the HTML below, you would get the following result:
HTML>BODY>UL>LI>UL>LI#sub2.subitem.otherclass
::WARNING:: .selector has been deprecated as of version 1.7, removed as of 1.9
The jQuery object has a selector property I saw when digging in its code yesterday. Don't know if it's defined in the docs are how reliable it is (for future proofing). But it works!
$('*').selector // returns *
Edit: If you were to find the selector inside the event, that information should ideally be part of the event itself and not the element because an element could have multiple click events assigned through various selectors. A solution would be to use a wrapper to around bind(), click() etc. to add events instead of adding it directly.
jQuery.fn.addEvent = function(type, handler) {
this.bind(type, {'selector': this.selector}, handler);
};
The selector is being passed as an object's property named selector. Access it as event.data.selector.
Let's try it on some markup (http://jsfiddle.net/DFh7z/):
<p class='info'>some text and <a>a link</a></p>​
$('p a').addEvent('click', function(event) {
alert(event.data.selector); // p a
});
Disclaimer: Remember that just as with live() events, the selector property may be invalid if DOM traversal methods are used.
<div><a>a link</a></div>
The code below will NOT work, as live relies on the selector property
which in this case is a.parent() - an invalid selector.
$('a').parent().live(function() { alert('something'); });
Our addEvent method will fire, but you too will see the wrong selector - a.parent().
In collaboration with #drzaus we've come up with the following jQuery plugin.
jQuery.getSelector
!(function ($, undefined) {
/// adapted http://jsfiddle.net/drzaus/Hgjfh/5/
var get_selector = function (element) {
var pieces = [];
for (; element && element.tagName !== undefined; element = element.parentNode) {
if (element.className) {
var classes = element.className.split(' ');
for (var i in classes) {
if (classes.hasOwnProperty(i) && classes[i]) {
pieces.unshift(classes[i]);
pieces.unshift('.');
}
}
}
if (element.id && !/\s/.test(element.id)) {
pieces.unshift(element.id);
pieces.unshift('#');
}
pieces.unshift(element.tagName);
pieces.unshift(' > ');
}
return pieces.slice(1).join('');
};
$.fn.getSelector = function (only_one) {
if (true === only_one) {
return get_selector(this[0]);
} else {
return $.map(this, function (el) {
return get_selector(el);
});
}
};
})(window.jQuery);
Minified Javascript
// http://stackoverflow.com/questions/2420970/how-can-i-get-selector-from-jquery-object/15623322#15623322
!function(e,t){var n=function(e){var n=[];for(;e&&e.tagName!==t;e=e.parentNode){if(e.className){var r=e.className.split(" ");for(var i in r){if(r.hasOwnProperty(i)&&r[i]){n.unshift(r[i]);n.unshift(".")}}}if(e.id&&!/\s/.test(e.id)){n.unshift(e.id);n.unshift("#")}n.unshift(e.tagName);n.unshift(" > ")}return n.slice(1).join("")};e.fn.getSelector=function(t){if(true===t){return n(this[0])}else{return e.map(this,function(e){return n(e)})}}}(window.jQuery)
Usage and Gotchas
<html>
<head>...</head>
<body>
<div id="sidebar">
<ul>
<li>
Home
</li>
</ul>
</div>
<div id="main">
<h1 id="title">Welcome</h1>
</div>
<script type="text/javascript">
// Simple use case
$('#main').getSelector(); // => 'HTML > BODY > DIV#main'
// If there are multiple matches then an array will be returned
$('body > div').getSelector(); // => ['HTML > BODY > DIV#main', 'HTML > BODY > DIV#sidebar']
// Passing true to the method will cause it to return the selector for the first match
$('body > div').getSelector(true); // => 'HTML > BODY > DIV#main'
</script>
</body>
</html>
Fiddle w/ QUnit tests
http://jsfiddle.net/CALY5/5/
Did you try this ?
$("*").click(function(){
$(this).attr("id");
});
Try this:
$("*").click(function(event){
console.log($(event.handleObj.selector));
});
Well, I wrote this simple jQuery plugin.
This checkes id or class name, and try to give as much exact selector as possible.
jQuery.fn.getSelector = function() {
if ($(this).attr('id')) {
return '#' + $(this).attr('id');
}
if ($(this).prop("tagName").toLowerCase() == 'body') return 'body';
var myOwn = $(this).attr('class');
if (!myOwn) {
myOwn = '>' + $(this).prop("tagName");
} else {
myOwn = '.' + myOwn.split(' ').join('.');
}
return $(this).parent().getSelector() + ' ' + myOwn;
}
Just add a layer over the $ function this way:
$ = (function(jQ) {
return (function() {
var fnc = jQ.apply(this,arguments);
fnc.selector = (arguments.length>0)?arguments[0]:null;
return fnc;
});
})($);
Now you can do things like $("a").selector and will return "a" even on newer jQuery versions.
http://www.selectorgadget.com/ is a bookmarklet designed explicitly for this use case.
That said, I agree with most other people in that you should just learn CSS selectors yourself, trying to generate them with code is not sustainable. :)
I added some fixes to #jessegavin's fix.
This will return right away if there is an ID on the element. I also added a name attribute check and a nth-child selector in case a element has no id, class, or name.
The name might need scoping in case there a multiple forms on the page and have similar inputs, but I didn't handle that yet.
function getSelector(el){
var $el = $(el);
var id = $el.attr("id");
if (id) { //"should" only be one of these if theres an ID
return "#"+ id;
}
var selector = $el.parents()
.map(function() { return this.tagName; })
.get().reverse().join(" ");
if (selector) {
selector += " "+ $el[0].nodeName;
}
var classNames = $el.attr("class");
if (classNames) {
selector += "." + $.trim(classNames).replace(/\s/gi, ".");
}
var name = $el.attr('name');
if (name) {
selector += "[name='" + name + "']";
}
if (!name){
var index = $el.index();
if (index) {
index = index + 1;
selector += ":nth-child(" + index + ")";
}
}
return selector;
}
I've released a jQuery plugin: jQuery Selectorator, you can get selector like this.
$("*").on("click", function(){
alert($(this).getSelector().join("\n"));
return false;
});
I was getting multiple elements even after above solutions, so i extended dds1024 work, for even more pin-pointing dom element.
e.g. DIV:nth-child(1) DIV:nth-child(3) DIV:nth-child(1) ARTICLE:nth-child(1) DIV:nth-child(1) DIV:nth-child(8) DIV:nth-child(2) DIV:nth-child(1) DIV:nth-child(2) DIV:nth-child(1) H4:nth-child(2)
Code:
function getSelector(el)
{
var $el = jQuery(el);
var selector = $el.parents(":not(html,body)")
.map(function() {
var i = jQuery(this).index();
i_str = '';
if (typeof i != 'undefined')
{
i = i + 1;
i_str += ":nth-child(" + i + ")";
}
return this.tagName + i_str;
})
.get().reverse().join(" ");
if (selector) {
selector += " "+ $el[0].nodeName;
}
var index = $el.index();
if (typeof index != 'undefined') {
index = index + 1;
selector += ":nth-child(" + index + ")";
}
return selector;
}
Taking in account some answers read here I'd like to propose this:
function getSelectorFromElement($el) {
if (!$el || !$el.length) {
return ;
}
function _getChildSelector(index) {
if (typeof index === 'undefined') {
return '';
}
index = index + 1;
return ':nth-child(' + index + ')';
}
function _getIdAndClassNames($el) {
var selector = '';
// attach id if exists
var elId = $el.attr('id');
if(elId){
selector += '#' + elId;
}
// attach class names if exists
var classNames = $el.attr('class');
if(classNames){
selector += '.' + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, '.');
}
return selector;
}
// get all parents siblings index and element's tag name,
// except html and body elements
var selector = $el.parents(':not(html,body)')
.map(function() {
var parentIndex = $(this).index();
return this.tagName + _getChildSelector(parentIndex);
})
.get()
.reverse()
.join(' ');
if (selector) {
// get node name from the element itself
selector += ' ' + $el[0].nodeName +
// get child selector from element ifself
_getChildSelector($el.index());
}
selector += _getIdAndClassNames($el);
return selector;
}
Maybe useful to create a jQuery plugin?
This can get you selector path of clicked HTML element-
$("*").on("click", function() {
let selectorPath = $(this).parents().map(function () {return this.tagName;}).get().reverse().join("->");
alert(selectorPath);
return false;
});
Are you trying to get the name of the current tag that was clicked?
If so, do this..
$("*").click(function(){
alert($(this)[0].nodeName);
});
You can't really get the "selector", the "selector" in your case is *.
Javascript code for the same, in case any one needs, as i needed it. This just the translation only of the above selected answer.
<script type="text/javascript">
function getAllParents(element){
var a = element;
var els = [];
while (a && a.nodeName != "#document") {
els.unshift(a.nodeName);
a = a.parentNode;
}
return els.join(" ");
}
function getJquerySelector(element){
var selector = getAllParents(element);
/* if(selector){
selector += " " + element.nodeName;
} */
var id = element.getAttribute("id");
if(id){
selector += "#" + id;
}
var classNames = element.getAttribute("class");
if(classNames){
selector += "." + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, ".");
}
console.log(selector);
alert(selector);
return selector;
}
</script>
Thank you p1nox!
My problem was to put focus back on an ajax call that was modifying part of the form.
$.ajax({ url : "ajax_invite_load.php",
async : true,
type : 'POST',
data : ...
dataType : 'html',
success : function(html, statut) {
var focus = $(document.activeElement).getSelector();
$td_left.html(html);
$(focus).focus();
}
});
I just needed to encapsulate your function in a jQuery plugin:
!(function ($, undefined) {
$.fn.getSelector = function () {
if (!this || !this.length) {
return ;
}
function _getChildSelector(index) {
if (typeof index === 'undefined') {
return '';
}
index = index + 1;
return ':nth-child(' + index + ')';
}
function _getIdAndClassNames($el) {
var selector = '';
// attach id if exists
var elId = $el.attr('id');
if(elId){
selector += '#' + elId;
}
// attach class names if exists
var classNames = $el.attr('class');
if(classNames){
selector += '.' + classNames.replace(/^\s+|\s+$/g, '').replace(/\s/gi, '.');
}
return selector;
}
// get all parents siblings index and element's tag name,
// except html and body elements
var selector = this.parents(':not(html,body)')
.map(function() {
var parentIndex = $(this).index();
return this.tagName + _getChildSelector(parentIndex);
})
.get()
.reverse()
.join(' ');
if (selector) {
// get node name from the element itself
selector += ' ' + this[0].nodeName +
// get child selector from element ifself
_getChildSelector(this.index());
}
selector += _getIdAndClassNames(this);
return selector;
}
})(window.jQuery);
This won't show you the DOM path, but it will output a string representation of what you see in eg chrome debugger, when viewing an object.
$('.mybtn').click( function(event){
console.log("%s", this); // output: "button.mybtn"
});
https://developer.chrome.com/devtools/docs/console-api#consolelogobject-object
How about:
var selector = "*"
$(selector).click(function() {
alert(selector);
});
I don't believe jQuery store the selector text that was used. After all, how would that work if you did something like this:
$("div").find("a").click(function() {
// what would expect the 'selector' to be here?
});
The best answer would be
var selector = '#something';
$(selector).anything(function(){
console.log(selector);
});

Categories

Resources