I have a div that has many classes. I select them all with
$('#mydiv').attr('class'); //outputs 'redball blueball greenbrick whitesquare'
What I actually need is the class that starts with 'red' so I really want to output only 'redball'. Is there an easy way to do this?
Like has already been said, split on spaces and find your matching class. Here's an example function:
<script language="javascript">
$(document).ready(function() {
var list = $('#mydiv').attr('class').split(/\s+/);
for (i = 0; i < list.length; i++) {
if (/red.*/.test(list[i])) {
alert(list[i]);
}
}
});
</script>
try to extract it with a regular expression:
split the output into an array an while itreating the array values try to test with some regulr expression (like this: /red[a-zA-Z09]*/)
hope it helps you
You can try the .hasClass() method to help you decide.
if( $( '#myDiv' ).attr( 'class' ).hasClass( 'redball' ) ) {
// call method to serve the redball...
}
Alternatively, using .split() and regex as suggested by the others can also work -- depends on how you want to use your output.
BONUS:
But for efficiency sake, it's better to cache the DOM object in a local variable and access that if you need to do more with the element. This is so that Javascript doesn't have to go back to the DOM tree and fetch the same object every time you want to use it.
var myDiv = $( '#myDiv' ); // store the <div> object in the variable
var classNames = myDiv.attr( 'class' );
switch( classNames ) {
case 'redball':
serveBall( 'red' );
break;
case 'blueball':
serveBall( 'blue' );
break;
.....
}
Related
There are several divs on my page with classes my_widget-2, my_widget-8, etc.
What JavaScript or jQuery code can I use to get the number "2" (ie. the number that appends the first matching widget)?
Note: If I were to write this question again, I would change the order of these class names and ask for a way to get "8" in order to avoid giving the impression that I want the smaller number.
$( "[class*='my_widget']" ).each ( function () {
var elClasses = $( this ).attr ( 'class' ).split ( ' ' );
for ( var index in elClasses ) {
if ( elClasses[index].match ( /^my_widget-\d+$/ ) ) {
var classNum = elClasses[index].split ( '-' )[1];
alert ( classNum );
break;
}
}
} );
Use the "attributeContains" selector to get all elements that have a class my_widget-*, and then loop trough all the classes the element has searching for you class. Once you find it, extract the number part.
This should do the trick:
$("[class^='my_widget']").each(function() {
var classParts = $(this).attr('class').split('-');
var number = classParts.pop();
});
Please note that it will only work if there is a singular class, otherwise you'd get something like 8 otherclass as a result.
Basic JS approach:
<div id="x" class="widget-2 lang-日本語">foo</div>
function Element_getClassArgument(el, name) {
var classes= el.className.split(' ');
var prefix= name+'-';
for (var i= classes.length; i-->0;)
if (classes[i].substring(0, prefix.length)==prefix)
return classes[i].substring(prefix.length);
return null;
}
Element_getClassArgument(document.getElementById('x'), 'widget'); // 2
If you wanted to include whitespace characters, or a hyphen in a name, you'd have to introduce an encoding scheme of some sort, for example encodeURIComponent. But often you can get away without that.
Wrapping in something with $ in the name is left as an exercise for the reader. :-)
If you want to get the DIV elements with a class my_widget-2, use this selector:
$("div.my_widget-2")
But if you want to get all DIV elements with a class of the form my_widget-N where N is an arbitrary number, try this:
$("div[class]").each(function() {
var matches = this.className.match(/(?:^|\s+)my_widget-(\d+)(?:\s+|$)/g);
if (matches !== null) {
alert(matches);
}
})
Try
element.attr('class').match(/my_widget-(\d+)/)[1]
It should return the column number as a string so just run parseInt() on it
doStuff(document.getElementById("myCircle1" "myCircle2" "myCircle3" "myCircle4"));
This doesn't work, so do I need a comma or semi-colon to make this work?
document.getElementById() only supports one name at a time and only returns a single node not an array of nodes. You have several different options:
You could implement your own function that takes multiple ids and returns multiple elements.
You could use document.querySelectorAll() that allows you to specify multiple ids in a CSS selector string .
You could put a common class names on all those nodes and use document.getElementsByClassName() with a single class name.
Examples of each option:
doStuff(document.querySelectorAll("#myCircle1, #myCircle2, #myCircle3, #myCircle4"));
or:
// put a common class on each object
doStuff(document.getElementsByClassName("circles"));
or:
function getElementsById(ids) {
var idList = ids.split(" ");
var results = [], item;
for (var i = 0; i < idList.length; i++) {
item = document.getElementById(idList[i]);
if (item) {
results.push(item);
}
}
return(results);
}
doStuff(getElementsById("myCircle1 myCircle2 myCircle3 myCircle4"));
This will not work, getElementById will query only one element by time.
You can use document.querySelectorAll("#myCircle1, #myCircle2") for querying more then one element.
ES6 or newer
With the new version of the JavaScript, you can also convert the results into an array to easily transverse it.
Example:
const elementsList = document.querySelectorAll("#myCircle1, #myCircle2");
const elementsArray = [...elementsList];
// Now you can use cool array prototypes
elementsArray.forEach(element => {
console.log(element);
});
How to query a list of IDs in ES6
Another easy way if you have an array of IDs is to use the language to build your query, example:
const ids = ['myCircle1', 'myCircle2', 'myCircle3'];
const elements = document.querySelectorAll(ids.map(id => `#${id}`).join(', '));
No, it won't work.
document.getElementById() method accepts only one argument.
However, you may always set classes to the elements and use getElementsByClassName() instead. Another option for modern browsers is to use querySelectorAll() method:
document.querySelectorAll("#myCircle1, #myCircle2, #myCircle3, #myCircle4");
I suggest using ES5 array methods:
["myCircle1","myCircle2","myCircle3","myCircle4"] // Array of IDs
.map(document.getElementById, document) // Array of elements
.forEach(doStuff);
Then doStuff will be called once for each element, and will receive 3 arguments: the element, the index of the element inside the array of elements, and the array of elements.
getElementByID is exactly that - get an element by id.
Maybe you want to give those elements a circle class and getElementsByClassName
document.getElementById() only takes one argument. You can give them a class name and use getElementsByClassName() .
Dunno if something like this works in js, in PHP and Python which i use quite often it is possible.
Maybe just use for loop like:
function doStuff(){
for(i=1; i<=4; i++){
var i = document.getElementById("myCiricle"+i);
}
}
Vulgo has the right idea on this thread. I believe his solution is the easiest of the bunch, although his answer could have been a little more in-depth. Here is something that worked for me. I have provided an example.
<h1 id="hello1">Hello World</h1>
<h2 id="hello2">Random</h2>
<button id="click">Click To Hide</button>
<script>
document.getElementById('click').addEventListener('click', function(){
doStuff();
});
function doStuff() {
for(var i=1; i<=2; i++){
var el = document.getElementById("hello" + i);
el.style.display = 'none';
}
}
</script>
Obviously just change the integers in the for loop to account for however many elements you are targeting, which in this example was 2.
The best way to do it, is to define a function, and pass it a parameter of the ID's name that you want to grab from the DOM, then every time you want to grab an ID and store it inside an array, then you can call the function
<p id="testing">Demo test!</p>
function grabbingId(element){
var storeId = document.getElementById(element);
return storeId;
}
grabbingId("testing").syle.color = "red";
You can use something like this whit array and for loop.
<p id='fisrt'>??????</p>
<p id='second'>??????</p>
<p id='third'>??????</p>
<p id='forth'>??????</p>
<p id='fifth'>??????</p>
<button id="change" onclick="changeColor()">color red</button>
<script>
var ids = ['fisrt','second','third','forth','fifth'];
function changeColor() {
for (var i = 0; i < ids.length; i++) {
document.getElementById(ids[i]).style.color='red';
}
}
</script>
For me worked flawles something like this
doStuff(
document.getElementById("myCircle1") ,
document.getElementById("myCircle2") ,
document.getElementById("myCircle3") ,
document.getElementById("myCircle4")
);
Use jQuery or similar to get access to the collection of elements in only one sentence. Of course, you need to put something like this in your html's "head" section:
<script type='text/javascript' src='url/to/my/jquery.1.xx.yy.js' ...>
So here is the magic:
.- First of all let's supose that you have some divs with IDs as you wrote, i.e.,
...some html...
<div id='MyCircle1'>some_inner_html_tags</div>
...more html...
<div id='MyCircle2'>more_html_tags_here</div>
...blabla...
<div id='MyCircleN'>more_and_more_tags_again</div>
...zzz...
.- With this 'spell' jQuery will return a collection of objects representing all div elements with IDs containing the entire string "myCircle" anywhere:
$("div[id*='myCircle']")
This is all! Note that you get rid of details like the numeric suffix, that you can manipulate all the divs in a single sentence, animate them... Voilá!
$("div[id*='myCircle']").addClass("myCircleDivClass").hide().fadeIn(1000);
Prove this in your browser's script console (press F12) right now!
As stated by jfriend00,
document.getElementById() only supports one name at a time and only returns a single node not an array of nodes.
However, here's some example code I created which you can give one or a comma separated list of id's. It will give you one or many elements in an array. If there are any errors, it will return an array with an Error as the only entry.
function safelyGetElementsByIds(ids){
if(typeof ids !== 'string') return new Error('ids must be a comma seperated string of ids or a single id string');
ids = ids.split(",");
let elements = [];
for(let i=0, len = ids.length; i<len; i++){
const currId = ids[i];
const currElement = (document.getElementById(currId) || new Error(currId + ' is not an HTML Element'));
if(currElement instanceof Error) return [currElement];
elements.push(currElement);
};
return elements;
}
safelyGetElementsByIds('realId1'); //returns [<HTML Element>]
safelyGetElementsByIds('fakeId1'); //returns [Error : fakeId1 is not an HTML Element]
safelyGetElementsByIds('realId1', 'realId2', 'realId3'); //returns [<HTML Element>,<HTML Element>,<HTML Element>]
safelyGetElementsByIds('realId1', 'realId2', 'fakeId3'); //returns [Error : fakeId3 is not an HTML Element]
If, like me, you want to create an or-like construction, where either of the elements is available on the page, you could use querySelector. querySelector tries locating the first id in the list, and if it can't be found continues to the next until it finds an element.
The difference with querySelectorAll is that it only finds a single element, so looping is not necessary.
document.querySelector('#myCircle1, #myCircle2, #myCircle3, #myCircle4');
here is the solution
if (
document.getElementById('73536573').value != '' &&
document.getElementById('1081743273').value != '' &&
document.getElementById('357118391').value != '' &&
document.getElementById('1238321094').value != '' &&
document.getElementById('1118122010').value != ''
) {
code
}
You can do it with document.getElementByID Here is how.
function dostuff (var here) {
if(add statment here) {
document.getElementById('First ID'));
document.getElementById('Second ID'));
}
}
There you go! xD
I found another similar question about this with a solution but it didn't work for me. I am new to jquery so thanks in advance for helping me solve my noobie question.
I am trying to use a variable for the class name. So that I can loop through the right fields based on this variable. My variable returns .reqfields4 but I get this error Error: Syntax error, unrecognized expression: ", if I enter the value manually, it works.
How can I achieve this? Thanks.
var reqsection='\".reqfields4\"';
$(".reqfields4").each ( function() {
//$(reqsection).each ( function() {
if(( $(this).val())==''){
some code...
}
else{
some code...
}
});
Just change var reqsection='\".reqfields4\"'; to var reqsection='.reqfields4'; - you don't need the inner string quotes.
You don't need quotes inside the value of the variable:
var reqsection = '.reqfields4';
$(reqsection).each( ... );
If you have a class name — just a class name — you can add the .:
var reqsection = 'reqfields4';
$('.' + reqsection).each( ... )
You can try like follows,
var reqsection=".reqfields4";
$(reqsection).each ( function() {
if(( $(this).val())==''){
some code...
}
else{
some code...
}
});
If you say var reqsection= '\".reqfields4\"';
then
$(reqsection).each( function() {});
Consider it like like you told jQuery this:
$(' ".reqfields4" ').each( function() {});
In other words you said: [ Please select now ".reqfields4" including the quotemarks ]. All class selectors must start with dot(.), but you just started your jQuery selector with a quotemark (") so of course it won't work at all (it won't try to select any classes, of course), and probably would throw an error from jQuery - I don't think ANY jQuery selector string can have quotemark(") as the actual first character of the selector!.
If you do this instead:
var reqsection= ".reqfields4";
$(".reqfields4").each( function() {});
$(reqsection).each( function() {});
The above two lines are equivalent.
What is the best way to get the complement of a jQuery selector's result set? I want to do something like the following:
jQuery(this).find("div:contains('someValue')").show();
But I want the complement of this selection hidden:
jQuery(this).find("div:not(:contains('someValue'))").hide();
Is there a more elegant solution to this than just executing the complementary selector? An alternative I can see is finding all divs first, storing the result, and filter this:
var results = jQuery(this).find("div");
results.find(":contains('someValue')").show();
results.find(":not(:contains('someValue'))").hide();
But that doesn't seem that much better. Any ideas?
var results = jQuery(this).find("div"),
selector = ":contains('someValue')";
results.filter(selector).show();
results.not(selector).hide();
as #Simon mentioned in the comments there is a way to improve this particular solution:
var results = jQuery("div", this),
selector = ":contains('someValue')";
results.filter(selector).show();
results.not(selector).hide();
Try like this,
jQuery(this).find("div").hide();
jQuery(this).find("div:contains('someValue')").show();
Well, I think your code is fairly good, but another option could be running this single statement:
jQuery(this).find("div").each(
function() {
var me = $(this);
var f = me.is(":contains('someValue')") ? "show" : "hide";
me[f]();
}
);
/** $.grepl
* uses a regular expression for text matching within an internal $.grep.
*/
$.extend({
"grepl": function(el, exp){
exp=new RegExp(exp,'gi'); // create RegExp
return $(
this.grep( el, function(n,i){ // run internal grep
return el[i].textContent.match(exp) != null; // match RegExp against textContent
})
);
}
});
$.grepl( $('div'), '^.*someRegexp.*$' ).css('display','none'); // usage of the function
I know that this does not exactly use the ":contains" expression, but the result should be the same.
I want to replace a particular string in (the text of) all the descendant elements of a given element.
innerHTML cannot be used as this sequence can appear in attributes. I have tried using XPath, but it seems the interface is essentially read-only. Because this is limited to one element, functions like document.getElementsByTagName cannot be used either.
Could any suggest any way to do this? Any jQuery or pure DOM method is acceptable.
Edit:
Some of the answers are suggesting the problem I was trying to work around: modifying the text directly on an Element will cause all non-Text child nodes to be removed.
So the problem essentially comes down to how to efficiently select all the Text nodes in a tree. In XPath, you can easily do it as //text(), but the current XPath interface does not allow you to change these Text nodes it seems.
One way to do this is by recursion as shown in the answer by Bergi. Another way is to use the find('*') selector of jQuery, but this is a bit more expensive. Still waiting to see if there' are better solutions.
Just use a simple selfmade DOM-iterator, which walks recursively over all nodes:
(function iterate_node(node) {
if (node.nodeType === 3) { // Node.TEXT_NODE
var text = node.data.replace(/any regular expression/g, "any replacement");
if (text != node.data) // there's a Safari bug
node.data = text;
} else if (node.nodeType === 1) { // Node.ELEMENT_NODE
for (var i = 0; i < node.childNodes.length; i++) {
iterate_node(node.childNodes[i]); // run recursive on DOM
}
}
})(content); // any dom node
A solution might be to surf through all available nodes (TextNodes included) and apply a regexp pattern on the results. To grab TextNodes as well, you need to invoke jQuerys .contents(). For instance:
var search = "foo",
replaceWith = 'bar',
pattern = new RegExp( search, 'g' );
function searchReplace( root ) {
$( root ).contents().each(function _repl( _, node ) {
if( node.nodeType === 3 )
node.nodeValue = node.nodeValue.replace( pattern, replaceWith );
else searchReplace( node );
});
}
$('#apply').on('click', function() {
searchReplace( document.getElementById('rootNode') );
});
Example: http://jsfiddle.net/h8Rxu/3/
Reference: .contents()
Using jQuery:
$('#parent').children().each(function () {
var that = $(this);
that.text(that.text().replace('test', 'foo'));
});
If you prefer to search through all children instead of just immediate children, use .find() instead.
http://jsfiddle.net/ExwDx/
Edit: Documentation for children, each, text, and find.
Sorry, just got it myself:
$('#id').find('*').each(function(){
$.each(this.childNodes, function() {
if (this.nodeType === 3) {
this.data = this.data.toUpperCase();
}
})
})
I used toUpperCase() here to make the result more obvious, but any String operation would be valid there.