Wildcards in HTML5 data attributes - javascript

Is it possible to find all DOM elements with jQuery with wildcards in the attribute name?
Consider the following HTML:
<input
id="val1"
type="text"
data-validate-required
data-validate-minlength="3"
data-validate-email />
What I am trying to achieve is to find all dom nodes with an attribute name starting with data-validate-
As far as I understand the wildcards described here are concerned with "value" of the attribute.
The reason for this is - I want to find out which elements should be validated at all - and afterwards find out which validation parameters (like -email) comes in play.
Thanks

You can create a custom pseudoclass to e.g. match attribute names against a regexp: http://jsfiddle.net/hN6vx/.
jQuery.expr.pseudos.attr = $.expr.createPseudo(function(arg) {
var regexp = new RegExp(arg);
return function(elem) {
for(var i = 0; i < elem.attributes.length; i++) {
var attr = elem.attributes[i];
if(regexp.test(attr.name)) {
return true;
}
}
return false;
};
});
Usage:
$(":attr('^data-')")

Because JQuery relies heavily on XPath, and XPath does not support wildcard attribute selection - it is not possible without the overhead you're looking to avoid.
There's always the possibility of creating your own selector, just to keep things clean:
//adds the :dataValidate selector
$.extend($.expr[':'],{
dataValidate: function(obj){
var i,dataAttrs=$(obj).data()
for (i in dataAttrs) {
if (i.substr(0,8)=='validate') return true;
}
return false;
}
})
Which will allow you to use :dataValidate in your normal jQuery selectors:
$(".element:dataValidate .etc")
Working JSFiddle: http://jsfiddle.net/rZXZ3/

You could loop over the atributes:
$('.element').each(function() {
$.each(this.attributes, function(i, att){
if(att.name.indexOf('data-validate')==0){
console.log(att.name);
}
});
});

You can use filter method and dataset object:
Allows access, both in reading and writing mode, to all the custom data attributes (data-*) set on the element. It is a map of DOMString, one entry for each custom data attribute.
$("input").filter(function(){
var state = false;
for (i in this.dataset)
if (i.indexOf('validate') > -1) state = true;
return state
})​
http://jsfiddle.net/Pxpfa/

Related

Modifying a string of html in javascript [duplicate]

I'm trying to get the HTML of a selected object with jQuery. I am aware of the .html() function; the issue is that I need the HTML including the selected object (a table row in this case, where .html() only returns the cells inside the row).
I've searched around and found a few very ‘hackish’ type methods of cloning an object, adding it to a newly created div, etc, etc, but this seems really dirty. Is there any better way, or does the new version of jQuery (1.4.2) offer any kind of outerHtml functionality?
I believe that currently (5/1/2012), all major browsers support the outerHTML function. It seems to me that this snippet is sufficient. I personally would choose to memorize this:
// Gives you the DOM element without the outside wrapper you want
$('.classSelector').html()
// Gives you the outside wrapper as well only for the first element
$('.classSelector')[0].outerHTML
// Gives you the outer HTML for all the selected elements
var html = '';
$('.classSelector').each(function () {
html += this.outerHTML;
});
//Or if you need a one liner for the previous code
$('.classSelector').get().map(function(v){return v.outerHTML}).join('');
EDIT: Basic support stats for element.outerHTML
Firefox (Gecko): 11 ....Released 2012-03-13
Chrome: 0.2 ...............Released 2008-09-02
Internet Explorer 4.0...Released 1997
Opera 7 ......................Released 2003-01-28
Safari 1.3 ...................Released 2006-01-12
No need to generate a function for it. Just do it like this:
$('a').each(function(){
var s = $(this).clone().wrap('<p>').parent().html();
console.log(s);
});
(Your browser's console will show what is logged, by the way. Most of the latest browsers since around 2009 have this feature.)
The magic is this on the end:
.clone().wrap('<p>').parent().html();
The clone means you're not actually disturbing the DOM. Run it without it and you'll see p tags inserted before/after all hyperlinks (in this example), which is undesirable. So, yes, use .clone().
The way it works is that it takes each a tag, makes a clone of it in RAM, wraps with p tags, gets the parent of it (meaning the p tag), and then gets the innerHTML property of it.
EDIT: Took advice and changed div tags to p tags because it's less typing and works the same.
2014 Edit : The question and this reply are from 2010. At the time, no better solution was widely available. Now, many of the other replies are better : Eric Hu's, or Re Capcha's for example.
This site seems to have a solution for you :
jQuery: outerHTML | Yelotofu
jQuery.fn.outerHTML = function(s) {
return s
? this.before(s).remove()
: jQuery("<p>").append(this.eq(0).clone()).html();
};
What about: prop('outerHTML')?
var outerHTML_text = $('#item-to-be-selected').prop('outerHTML');
And to set:
$('#item-to-be-selected').prop('outerHTML', outerHTML_text);
It worked for me.
PS: This is added in jQuery 1.6.
Extend jQuery:
(function($) {
$.fn.outerHTML = function() {
return $(this).clone().wrap('<div></div>').parent().html();
};
})(jQuery);
And use it like this: $("#myTableRow").outerHTML();
I agree with Arpan (Dec 13 '10 5:59).
His way of doing it is actually a MUCH better way of doing it, as you dont use clone. The clone method is very time consuming, if you have child elements, and nobody else seemed to care that IE actually HAVE the outerHTML attribute (yes IE actually have SOME useful tricks up its sleeve).
But I would probably create his script a bit different:
$.fn.outerHTML = function() {
var $t = $(this);
if ($t[0].outerHTML !== undefined) {
return $t[0].outerHTML;
} else {
var content = $t.wrap('<div/>').parent().html();
$t.unwrap();
return content;
}
};
To be truly jQuery-esque, you might want outerHTML() to be a getter and a setter and have its behaviour as similar to html() as possible:
$.fn.outerHTML = function (arg) {
var ret;
// If no items in the collection, return
if (!this.length)
return typeof arg == "undefined" ? this : null;
// Getter overload (no argument passed)
if (!arg) {
return this[0].outerHTML ||
(ret = this.wrap('<div>').parent().html(), this.unwrap(), ret);
}
// Setter overload
$.each(this, function (i, el) {
var fnRet,
pass = el,
inOrOut = el.outerHTML ? "outerHTML" : "innerHTML";
if (!el.outerHTML)
el = $(el).wrap('<div>').parent()[0];
if (jQuery.isFunction(arg)) {
if ((fnRet = arg.call(pass, i, el[inOrOut])) !== false)
el[inOrOut] = fnRet;
}
else
el[inOrOut] = arg;
if (!el.outerHTML)
$(el).children().unwrap();
});
return this;
}
Working demo: http://jsfiddle.net/AndyE/WLKAa/
This allows us to pass an argument to outerHTML, which can be
a cancellable function — function (index, oldOuterHTML) { } — where the return value will become the new HTML for the element (unless false is returned).
a string, which will be set in place of the HTML of each element.
For more information, see the jQuery docs for html().
You can also use get (Retrieve the DOM elements matched by the jQuery object.).
e.g:
$('div').get(0).outerHTML;//return "<div></div>"
As extension method :
jQuery.fn.outerHTML = function () {
return this.get().map(function (v) {
return v.outerHTML
}).join()
};
Or
jQuery.fn.outerHTML = function () {
return $.map(this.get(), function (v) {
return v.outerHTML
}).join()
};
Multiple choice and return the outer html of all matched elements.
$('input').outerHTML()
return:
'<input id="input1" type="text"><input id="input2" type="text">'
To make a FULL jQuery plugin as .outerHTML, add the following script to any js file and include after jQuery in your header:
update New version has better control as well as a more jQuery Selector friendly service! :)
;(function($) {
$.extend({
outerHTML: function() {
var $ele = arguments[0],
args = Array.prototype.slice.call(arguments, 1)
if ($ele && !($ele instanceof jQuery) && (typeof $ele == 'string' || $ele instanceof HTMLCollection || $ele instanceof Array)) $ele = $($ele);
if ($ele.length) {
if ($ele.length == 1) return $ele[0].outerHTML;
else return $.map($("div"), function(ele,i) { return ele.outerHTML; });
}
throw new Error("Invalid Selector");
}
})
$.fn.extend({
outerHTML: function() {
var args = [this];
if (arguments.length) for (x in arguments) args.push(arguments[x]);
return $.outerHTML.apply($, args);
}
});
})(jQuery);
This will allow you to not only get the outerHTML of one element, but even get an Array return of multiple elements at once! and can be used in both jQuery standard styles as such:
$.outerHTML($("#eleID")); // will return outerHTML of that element and is
// same as
$("#eleID").outerHTML();
// or
$.outerHTML("#eleID");
// or
$.outerHTML(document.getElementById("eleID"));
For multiple elements
$("#firstEle, .someElesByClassname, tag").outerHTML();
Snippet Examples:
console.log('$.outerHTML($("#eleID"))'+"\t", $.outerHTML($("#eleID")));
console.log('$("#eleID").outerHTML()'+"\t\t", $("#eleID").outerHTML());
console.log('$("#firstEle, .someElesByClassname, tag").outerHTML()'+"\t", $("#firstEle, .someElesByClassname, tag").outerHTML());
var checkThisOut = $("div").outerHTML();
console.log('var checkThisOut = $("div").outerHTML();'+"\t\t", checkThisOut);
$.each(checkThisOut, function(i, str){ $("div").eq(i).text("My outerHTML Was: " + str); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://rawgit.com/JDMcKinstry/ce699e82c7e07d02bae82e642fb4275f/raw/deabd0663adf0d12f389ddc03786468af4033ad2/jQuery.outerHTML.js"></script>
<div id="eleID">This will</div>
<div id="firstEle">be Replaced</div>
<div class="someElesByClassname">At RunTime</div>
<h3><tag>Open Console to see results</tag></h3>
you can also just do it this way
document.getElementById(id).outerHTML
where id is the id of the element that you are looking for
I used Jessica's solution (which was edited by Josh) to get outerHTML to work on Firefox. The problem however is that my code was breaking because her solution wrapped the element into a DIV. Adding one more line of code solved that problem.
The following code gives you the outerHTML leaving the DOM tree unchanged.
$jq.fn.outerHTML = function() {
if ($jq(this).attr('outerHTML'))
return $jq(this).attr('outerHTML');
else
{
var content = $jq(this).wrap('<div></div>').parent().html();
$jq(this).unwrap();
return content;
}
}
And use it like this: $("#myDiv").outerHTML();
Hope someone finds it useful!
// no cloning necessary
var x = $('#xxx').wrapAll('<div></div>').parent().html();
alert(x);
Fiddle here: http://jsfiddle.net/ezmilhouse/Mv76a/
If the scenario is appending a new row dynamically, you can use this:
var row = $(".myRow").last().clone();
$(".myRow").last().after(row);
.myrow is the classname of the <tr>. It makes a copy of the last row and inserts that as a new last row.
This also works in IE7, while the [0].outerHTML method does not allow assignments in ie7
node.cloneNode() hardly seems like a hack. You can clone the node and append it to any desired parent element, and also manipulate it by manipulating individual properties, rather than having to e.g. run regular expressions on it, or add it in to the DOM, then manipulate it afterwords.
That said, you could also iterate over the attributes of the element to construct an HTML string representation of it. It seems likely this is how any outerHTML function would be implemented were jQuery to add one.
I've used Volomike's solution updated by Jessica. Just added a check to see if the element exists, and made it return blank in case it doesn't.
jQuery.fn.outerHTML = function() {
return $(this).length > 0 ? $(this).clone().wrap('<div />').parent().html() : '';
};
Of course, use it like:
$('table#buttons').outerHTML();
You can find a good .outerHTML() option here https://github.com/darlesson/jquery-outerhtml.
Unlike .html() that returns only the element's HTML content, this version of .outerHTML() returns the selected element and its HTML content or replaces it as .replaceWith() method but with the difference that allows the replacing HTML to be inherit by the chaining.
Examples can also be seeing in the URL above.
This is quite simple with vanilla JavaScript...
document.querySelector('#selector')
Note that Josh's solution only works for a single element.
Arguably, "outer" HTML only really makes sense when you have a single element, but there are situations where it makes sense to take a list of HTML elements and turn them into markup.
Extending Josh's solution, this one will handle multiple elements:
(function($) {
$.fn.outerHTML = function() {
var $this = $(this);
if ($this.length>1)
return $.map($this, function(el){ return $(el).outerHTML(); }).join('');
return $this.clone().wrap('<div/>').parent().html();
}
})(jQuery);
Edit: another problem with Josh's solution fixed, see comment above.
Anothe similar solution with added remove() of the temporary DOM object.
I have made this simple test with outerHTML being tokimon solution (without clone), and outerHTML2 being jessica solution (clone)
console.time("outerHTML");
for(i=0;i<1000;i++)
{
var html = $("<span style='padding:50px; margin:50px; display:block'><input type='text' title='test' /></span>").outerHTML();
}
console.timeEnd("outerHTML");
console.time("outerHTML2");
for(i=0;i<1000;i++)
{
var html = $("<span style='padding:50px; margin:50px; display:block'><input type='text' title='test' /></span>").outerHTML2();
}
console.timeEnd("outerHTML2");
and the result in my chromium (Version 20.0.1132.57 (0)) browser was
outerHTML: 81ms
outerHTML2: 439ms
but if we use tokimon solution without the native outerHTML function (which is now supported in probably almost every browser)
we get
outerHTML: 594ms
outerHTML2: 332ms
and there are gonna be more loops and elements in real world examples, so the perfect combination would be
$.fn.outerHTML = function()
{
$t = $(this);
if( "outerHTML" in $t[0] ) return $t[0].outerHTML;
else return $t.clone().wrap('<p>').parent().html();
}
so clone method is actually faster than wrap/unwrap method
(jquery 1.7.2)
Here is a very optimized outerHTML plugin for jquery:
(http://jsperf.com/outerhtml-vs-jquery-clone-hack/5 => the 2 others fast code snippets are not compatible with some browsers like FF < 11)
(function($) {
var DIV = document.createElement("div"),
outerHTML;
if ('outerHTML' in DIV) {
outerHTML = function(node) {
return node.outerHTML;
};
} else {
outerHTML = function(node) {
var div = DIV.cloneNode();
div.appendChild(node.cloneNode(true));
return div.innerHTML;
};
}
$.fn.outerHTML = function() {
return this.length ? outerHTML(this[0]) : void(0);
};
})(jQuery);
#Andy E => I don't agree with you. outerHMTL doesn't need a getter AND a setter: jQuery already give us 'replaceWith'...
#mindplay => Why are you joining all outerHTML? jquery.html return only the HTML content of the FIRST element.
(Sorry, don't have enough reputation to write comments)
Short and sweet.
[].reduce($('.x'), function(i,v) {return i+v.outerHTML}, '')
or event more sweet with help of arrow functions
[].reduce.call($('.x'), (i,v) => i+v.outerHTML, '')
or without jQuery at all
[].reduce.call(document.querySelectorAll('.x'), (i,v) => i+v.outerHTML, '')
or if you don't like this approach, check that
$('.x').get().reduce((i,v) => i+v.outerHTML, '')
This is great for changing elements on the dom but does NOT work for ie when passing in a html string into jquery like this:
$('<div id="foo">Some <span id="blog">content</span></div>').find('#blog').outerHTML();
After some manipulation I have created a function which allows the above to work in ie for html strings:
$.fn.htmlStringOuterHTML = function() {
this.parent().find(this).wrap('<div/>');
return this.parent().html();
};
$.html = el => $("<div>"+el+"</div>").html().trim();
I came across this while looking for an answer to my issue which was that I was trying to remove a table row then add it back in at the bottom of the table (because I was dynamically creating data rows but wanted to show an 'Add New Record' type row at the bottom).
I had the same issue, in that it was returning the innerHtml so was missing the TR tags, which held the ID of that row and meant it was impossible to repeat the procedure.
The answer I found was that the jquery remove() function actually returns the element, that it removes, as an object. So, to remove and re-add a row it was as simple as this...
var a = $("#trRowToRemove").remove();
$('#tblMyTable').append(a);
If you're not removing the object but want to copy it somewhere else, use the clone() function instead.
jQuery plugin as a shorthand to directly get the whole element HTML:
jQuery.fn.outerHTML = function () {
return jQuery('<div />').append(this.eq(0).clone()).html();
};
And use it like this: $(".element").outerHTML();
Pure JavaScript:
var outerHTML = function(node) {
var div = document.createElement("div");
div.appendChild(node.cloneNode(true));
return div.innerHTML;
};
$("#myNode").parent(x).html();
Where 'x' is the node number, beginning with 0 as the first one, should get the right node you want, if you're trying to get a specific one. If you have child nodes, you should really be putting an ID on the one you want, though, to just zero in on that one. Using that methodology and no 'x' worked fine for me.
Simple solution.
var myself = $('#div').children().parent();
$("#myTable").parent().html();
Perhaps I'm not understanding your question properly, but this will get the selected element's parent element's html.
Is that what you're after?

Using Jquery Filter as a way to filter links on a page

I have a list of links on a page and a set of checkboxes that should filter the links so that only the ones that have the specific criteria will be active. My rudimentary attempt to do this involves creating an array of all the filter options that are active and running a .filter(Array) to make those active and a .not(Array) to disable the other links.
The problem is that if more than one filter options is selected any link that matches either filter option will be active. When in reality what i want is only the links that match ALL the filter options to be active.
Here is my stripped down version in jsFiddle
var filterAll = ["filter-F_0", "filter-F_1", "filter-F_2", "filter-F_3", "filter-F_4", "filter-P_0", "filter-P_1", "filter-P_2", "filter-P_3", ]
var filterActive = [];
function filterApps(){
if(filterActive.length == 0)
{
filterReset();
return;
}
var arrActive = $.map(filterActive, function (val) {
return '[' + val + ']'
}).join(",")
addToLog("arr = " + arrActive);
$(".appLink").filter(arrActive).css(activeAppCSS).addClass("active").removeClass("disable");
$(".appLink").not(arrActive).css(disabledAPPCSS).addClass("disable").removeClass("active");}
You have complicated many things here, using attribute's name for filtering the elements is a terrible idea (sorry), you could use data-* attributes that store the filtering criteria in an array. If I have understood the question correctly something like the following should work, this solution reads the attributes' name using attributes property, it should be noted that it's not the most efficient way of doing the task and as Array object's .filter() method is used it doesn't work in older browsers that don't support ES5, for supporting those browsers you can use a shim.
var $links = $('.appLink');
var $checkboxes = $('input[type=checkbox]').on('change', function () {
// Creating an array of values
var checked = $checkboxes.filter(':checked').map(function () {
return this.value.toLowerCase();
}).get();
// Filtering the .appLink elements by reading the attributes
// and comparing the filtered array's length with the checked one
$links.removeClass('matched').filter(function () {
return [].slice.call(this.attributes).filter(function (a) {
return a.name.indexOf('filter') === 0;
}).filter(function(f) {
return $.inArray(f.name.replace('filter-', ''), checked) > -1;
}).length === checked.length;
}).addClass('matched');
});
http://jsfiddle.net/85tTp/
In case that you want to use data-* properties, you can define an attribute like data-filter='["f1", "f2", ""]' for the elements and use jQuery .data() method for reading them:
$links.removeClass('matched').filter(function () {
return $(this).data('filter').filter(function(f) {
return $.inArray(f, checked) > -1;
}).length === checked.length;
}).addClass('matched');

JavaScript selector for data-event?

Is there a way to select an element based on the data-event attribute?
Here is what I have:
<button data-event="5456293788" class="id-button-yes greenBtn list-buy-buttons">Buy now!</button>
Looking for something like:
document.getElementByDataEvent('5456293788')
Possible?
Something like this?
document.querySelector("button[data-event='5456293788']");
See in JSFiddle
It has quite a wide browser support (even IE 8 supports it)
Use the attribute selector
http://jsfiddle.net/QTNzf/
JS
document.querySelector('button[data-event="5456293788"]' );
CSS
button[data-devent="5456293788"] {
background-color: #eee;
}
The attribute selector does spring to mind, and you don't need jQuery to use that.
It probably won't work on older browsers, though.
If you really want, you can add a getElementsByDataEvent to the document object (not sure if all browsers allow this):
document.getElementsByDataEvent = function(dataEvent)
{
return document.querySelectorAll('[data-event="'+dataEvent+'"]');
};
But as you can see, this is a bit unnecessary, since it's just returning the return-value of a querySelectorAll call. What's more, if you use querySelectorAll directly, you can do something like this
document.querySelectorAll('a[data-event="foo"]');//only links will be retured
//or, with some other data-* thing, along the lines of:
document.querySelectorAll('[class="greenBtn"]');
Use the attribute equals selector in jQuery:
$('[data-event="5456293788"]')
or with document.querySelectorAll:
document.querySelectorAll('[data-event="5456293788"]');
For backwards compatibility, you'd have to iterate through all the elements checking the attribute values. This is a case where a library such as jQuery really helps.
backwards compatible raw js:
function getElementsByAttr(attr, val) {
var nodes,
node,
i,
ret;
val = '' + val;
nodes = document.getElementsByTagName('*');
ret = [];
for (i = 0; i < nodes.length; i += 1) {
node = nodes[i];
if (node.getAttribute(attr) === val) {
ret.push(node);
}
}
return ret;
}
de = getElementsByAttr('data-event', '5456293788');

Getting element by a custom attribute using JavaScript

I have an XHTML page where each HTML element has a unique custom attribute, like this:
<div class="logo" tokenid="14"></div>
I need a way to find this element by ID, similar to document.getElementById(), but instead of using a general ID, I want to search for the element using my custom "tokenid" attribute. Something like this:
document.getElementByTokenId('14');
Is that possible? If yes - any hint would be greatly appreciated.
Thanks.
It is not good to use custom attributes in the HTML. If any, you should use HTML5's data attributes.
Nevertheless you can write your own function that traverses the tree, but that will be quite slow compared to getElementById because you cannot make use of any index:
function getElementByAttribute(attr, value, root) {
root = root || document.body;
if(root.hasAttribute(attr) && root.getAttribute(attr) == value) {
return root;
}
var children = root.children,
element;
for(var i = children.length; i--; ) {
element = getElementByAttribute(attr, value, children[i]);
if(element) {
return element;
}
}
return null;
}
In the worst case, this will traverse the whole tree. Think about how to change your concept so that you can make use browser functions as much as possible.
In newer browsers you use of the querySelector method, where it would just be:
var element = document.querySelector('[tokenid="14"]');
This will be much faster too.
Update: Please note #Andy E's comment below. It might be that you run into problems with IE (as always ;)). If you do a lot of element retrieval of this kind, you really should consider using a JavaScript library such as jQuery, as the others mentioned. It hides all these browser differences.
<div data-automation="something">
</div>
document.querySelector("div[data-automation]")
=> finds the div
document.querySelector("div[data-automation='something']")
=> finds the div with a value
If you're using jQuery, you can use some of their selector magic to do something like this:
$('div[tokenid=14]')
as your selector.
You can accomplish this with JQuery:
$('[tokenid=14]')
Here's a fiddle for an example.
If you're willing to use JQuery, then:
var myElement = $('div[tokenid="14"]').get();
Doing this with vanilla JavaScript will do the trick:
const something = document.querySelectorAll('[data-something]')
Use this more stable Function:
function getElementsByAttribute(attr, value) {
var match = [];
/* Get the droids we are looking for*/
var elements = document.getElementsByTagName("*");
/* Loop through all elements */
for (var ii = 0, ln = elements.length; ii < ln; ii++) {
if (elements[ii].nodeType === 1){
if (elements[ii].name != null){
/* If a value was passed, make sure it matches the elements */
if (value) {
if (elements[ii].getAttribute(attr) === value)
match.push(elements[ii]);
} else {
/* Else, simply push it */
match.push(elements[ii]);
}
}
}
}
return match;
};

Get class list for element with jQuery

Is there a way in jQuery to loop through or assign to an array all of the classes that are assigned to an element?
ex.
<div class="Lorem ipsum dolor_spec sit amet">Hello World!</div>
I will be looking for a "special" class as in "dolor_spec" above. I know that I could use hasClass() but the actual class name may not necessarily be known at the time.
You can use document.getElementById('divId').className.split(/\s+/); to get you an array of class names.
Then you can iterate and find the one you want.
var classList = document.getElementById('divId').className.split(/\s+/);
for (var i = 0; i < classList.length; i++) {
if (classList[i] === 'someClass') {
//do something
}
}
jQuery does not really help you here...
var classList = $('#divId').attr('class').split(/\s+/);
$.each(classList, function(index, item) {
if (item === 'someClass') {
//do something
}
});
Why has no one simply listed.
$(element).attr("class").split(/\s+/);
EDIT: Split on /\s+/ instead of ' ' to fix #MarkAmery's objection. (Thanks #YashaOlatoto.)
On supporting browsers, you can use DOM elements' classList property.
$(element)[0].classList
It is an array-like object listing all of the classes the element has.
If you need to support old browser versions that don't support the classList property, the linked MDN page also includes a shim for it - although even the shim won't work on Internet Explorer versions below IE 8.
Here is a jQuery plugin which will return an array of all the classes the matched element(s) have
;!(function ($) {
$.fn.classes = function (callback) {
var classes = [];
$.each(this, function (i, v) {
var splitClassName = v.className.split(/\s+/);
for (var j = 0; j < splitClassName.length; j++) {
var className = splitClassName[j];
if (-1 === classes.indexOf(className)) {
classes.push(className);
}
}
});
if ('function' === typeof callback) {
for (var i in classes) {
callback(classes[i]);
}
}
return classes;
};
})(jQuery);
Use it like
$('div').classes();
In your case returns
["Lorem", "ipsum", "dolor_spec", "sit", "amet"]
You can also pass a function to the method to be called on each class
$('div').classes(
function(c) {
// do something with each class
}
);
Here is a jsFiddle I set up to demonstrate and test http://jsfiddle.net/GD8Qn/8/
Minified Javascript
;!function(e){e.fn.classes=function(t){var n=[];e.each(this,function(e,t){var r=t.className.split(/\s+/);for(var i in r){var s=r[i];if(-1===n.indexOf(s)){n.push(s)}}});if("function"===typeof t){for(var r in n){t(n[r])}}return n}}(jQuery);
You should try this one:
$("selector").prop("classList")
It returns a list of all current classes of the element.
var classList = $(element).attr('class').split(/\s+/);
$(classList).each(function(index){
//do something
});
$('div').attr('class').split(' ').each(function(cls){ console.log(cls);})
Update:
As #Ryan Leonard pointed out correctly, my answer doesn't really fix the point I made my self... You need to both trim and remove double spaces with (for example) string.replace(/ +/g, " ").. Or you could split the el.className and then remove empty values with (for example) arr.filter(Boolean).
const classes = element.className.split(' ').filter(Boolean);
or more modern
const classes = element.classList;
Old:
With all the given answers, you should never forget to user .trim() (or $.trim())
Because classes gets added and removed, it can happen that there are multiple spaces between class string.. e.g. 'class1 class2 class3'..
This would turn into ['class1', 'class2','','','', 'class3']..
When you use trim, all multiple spaces get removed..
Might this can help you too. I have used this function to get classes of childern element..
function getClickClicked(){
var clickedElement=null;
var classes = null;<--- this is array
ELEMENT.on("click",function(e){//<-- where element can div,p span, or any id also a class
clickedElement = $(e.target);
classes = clickedElement.attr("class").split(" ");
for(var i = 0; i<classes.length;i++){
console.log(classes[i]);
}
e.preventDefault();
});
}
In your case you want doler_ipsum class u can do like this now calsses[2];.
Thanks for this - I was having a similar issue, as I'm trying to programatically relate objects will hierarchical class names, even though those names might not necessarily be known to my script.
In my script, I want an <a> tag to turn help text on/off by giving the <a> tag [some_class] plus the class of toggle, and then giving it's help text the class of [some_class]_toggle. This code is successfully finding the related elements using jQuery:
$("a.toggle").toggle(function(){toggleHelp($(this), false);}, function(){toggleHelp($(this), true);});
function toggleHelp(obj, mode){
var classList = obj.attr('class').split(/\s+/);
$.each( classList, function(index, item){
if (item.indexOf("_toggle") > 0) {
var targetClass = "." + item.replace("_toggle", "");
if(mode===false){$(targetClass).removeClass("off");}
else{$(targetClass).addClass("off");}
}
});
}
Try This. This will get you the names of all the classes from all the elements of document.
$(document).ready(function() {
var currentHtml="";
$('*').each(function() {
if ($(this).hasClass('') === false) {
var class_name = $(this).attr('class');
if (class_name.match(/\s/g)){
var newClasses= class_name.split(' ');
for (var i = 0; i <= newClasses.length - 1; i++) {
if (currentHtml.indexOf(newClasses[i]) <0) {
currentHtml += "."+newClasses[i]+"<br>{<br><br>}<br>"
}
}
}
else
{
if (currentHtml.indexOf(class_name) <0) {
currentHtml += "."+class_name+"<br>{<br><br>}<br>"
}
}
}
else
{
console.log("none");
}
});
$("#Test").html(currentHtml);
});
Here is the working example: https://jsfiddle.net/raju_sumit/2xu1ujoy/3/
For getting the list of classes applied to element we can use
$('#elementID').prop('classList')
For adding or removing any classes we can follow as below.
$('#elementID').prop('classList').add('yourClassName')
$('#elementID').prop('classList').remove('yourClassName')
And for simply checking if the class is present or not we can use hasClass
I had a similar issue, for an element of type image. I needed to check whether the element was of a certain class. First I tried with:
$('<img>').hasClass("nameOfMyClass");
but I got a nice "this function is not available for this element".
Then I inspected my element on the DOM explorer and I saw a very nice attribute that I could use: className. It contained the names of all the classes of my element separated by blank spaces.
$('img').className // it contains "class1 class2 class3"
Once you get this, just split the string as usual.
In my case this worked:
var listOfClassesOfMyElement= $('img').className.split(" ");
I am assuming this would work with other kinds of elements (besides img).
Hope it helps.
javascript provides a classList attribute for a node element in dom. Simply using
element.classList
will return a object of form
DOMTokenList {0: "class1", 1: "class2", 2: "class3", length: 3, item: function, contains: function, add: function, remove: function…}
The object has functions like contains, add, remove which you can use
A bit late, but using the extend() function lets you call "hasClass()" on any element, e.g.:
var hasClass = $('#divId').hasClass('someClass');
(function($) {
$.extend({
hasClass: new function(className) {
var classAttr = $J(this).attr('class');
if (classAttr != null && classAttr != undefined) {
var classList = classAttr.split(/\s+/);
for(var ix = 0, len = classList.length;ix < len;ix++) {
if (className === classList[ix]) {
return true;
}
}
}
return false;
}
}); })(jQuery);
The question is what Jquery is designed to do.
$('.dolor_spec').each(function(){ //do stuff
And why has no one given .find() as an answer?
$('div').find('.dolor_spec').each(function(){
..
});
There is also classList for non-IE browsers:
if element.classList.contains("dolor_spec") { //do stuff

Categories

Resources