Javascript: Check if classname exists - javascript

<div class="Trade">
<div id="Offer">
<div class="NoResults">No Result!</div>
<div class="FooterPager"> <span id="Offer"><a disabled="disabled">First</a> <a disabled="disabled">Previous</a> <a disabled="disabled">Next</a> <a disabled="disabled">Last</a> </span>
</div>
</div>
</div>
Here is my javascript:
function Check(){
return !(iframe.contentDocument.getElementById("Offer").firstElementChild.tagName.toLowerCase() == "table");
}
Is it possible to return a true or false value to check if the class "NoResult" exists? If so, how do I do it? You guys rocks. I can't change the HTML coding, only the javascript.

Use classList.
var hasClass = element.classList.contains('some-class');
Further Reading (disclaimer: link to my own post).
If not supported in your target platforms, then try...
var hasClass = (" " + element.className + " ").indexOf(" some-class ") > -1;

if ( ~(' ' + element.className + ' ').indexOf(' NoResult ') ) {
// here you go. You've got that class...
}

In Javascript without using a library like jQuery, you could do it by:
(' ' + MyElement.className + ' ').indexOf(' MyClassName ') != -1
This evaluates to true when "MyClassName" appears anywhere by itself inside the string as defined on the className property.
In your specific case, something like:
function Check()
{
//Returns true when it exists
return (' ' + iframe.contentDocument.getElementById('Offer').firstElementChild.className + ' ').indexOf(' NoResults ') != -1;
}
There was previously a mistake in my answer where it would incorrectly identify a partial match as pointed out in the comments. Basically, you need to consider in the check that the class name is whole. A neat way to do this (like the other answers show) is that if you spaces before and after both the entire className property and the class you are searching for, it will always find the whole class.
While this will work, I recommend Alex's answer as while classList isn't available in every browser (<= IE9 and a few others), it is a neater solution to the problem.

How to check if an element has a class for all browsers:
JQuery 1.6 or lower
if($("#ElementId").attr('class').indexOf('ClassName') > -1)
JQuery 1.6 or higher
if($("#ElementId").prop('class').indexOf('ClassName') > -1)
Or, if you are not going to use IE at all
if($("#ElementId").prop('class').includes('ClassName'))

Related

Preventing an element having duplicate classnames

I would like to prevent duplicate classnames on an element using JavaScript.
When I run the following code, I get the classname "Test 1" twice.
Here's my HTML:
<body>
<div id="foo">Hey</div>
</body>
and my Javascript:
function addClass(element, myClass) {
var add = element.className += ' ' + myClass;
}
addClass(foo,'Test1');
addClass(foo,'Test1');
addClass(foo, 'Test2');
I would like my result to be:
<div id="foo" class=" Test1 Test2">Hey</div>
and not
<div id="foo" class=" Test1 Test1 Test2">Hey</div>
Is there any way I can achieve this?
Use the string.contains() method when adding the class; try something like
function addClass(element, myClass) {
if(!element.className.contains(myClass))
element.className += ' ' + myClass;
}
EDIT
Use string.split(" ") to break the class names up (to avoid matching partial class names), then use indexOf to check to see if the class has been added already. Something like
function addClass(element, myClass) {
if(element.className.split(" ").indexOf(myClass)==-1)
element.className += ' ' + myClass;
}
jsFiddle here.
Use indexOf() to see if it already has that class. Note that the solution by itself would cause problems when having classes that contain part of another, so I've slightly changed it (New solution is a little ugly but meh)
function addClass(element, myClass) {
if((" " +element.className+ " ").indexOf(" "+myClass+" ") == -1)
element.className += ' ' + myClass;
}
I suppose if you are adding a class you want that class to have precedence- if it exists already but was superceded in the cascade by another class, move the old instance to the end of the class definitition-
function addCLass(who,cname){
var rx= RegExp('\\b'+cname+'\\b','g'),
C=who.className.replace(rx,'').split(/\s+/).push(cname);
who.className= C.join(' ');
}

jQuery show, get element by name

I'm creating a news page. I need to find out if there is set an anchor to an article. If not, I just show the latest article. An example URL with anchor is: example.com/news.php#article43
The HTML structure is:
<div>
<a name="article43"></a>
<h2>TITLE</h2>
<div class="news_content"></div>
</div>
And my JS is this:
var anchor = $(location).attr('href').split('#');
if(anchor[1]){
$('a[name=' + anchor[1] + ']').next('.news_content').show();
}else{
$('.news_content').first().show();
}
Something doesn't work.
next will only return the immediate sibling after the element, you probably want nextAll:
$('a[name=' + anchor[1] + ']').nextAll('.news_content').show();
or, if your HTML structure doesn't involve wrapping, ie:
<div>
<a name="article43"></a>
<h2>TITLE</h2>
<div class="news_content"></a>
<a name="article44"></a>
<h2>TITLE</h2>
<div class="news_content"></a>
</div>
You'd want: http://jsfiddle.net/AVg3y/
$('a[name=' + anchor[1] + ']').nextAll('.news_content').first().show();
Also, this is probably just a typo, but your HTML is malformed. It should be:
<div>
<a name="article43"></a>
<h2>TITLE</h2>
<div class="news_content"></div> //<-- oops
</div>
Try this (use siblings instead of next):
var anchor = location.href.split('#');
if(anchor[1]) {
$('a[name=' + anchor[1] + ']').siblings('.news_content').show();
} else {
$('.news_content').first().show();
}
You can get the hash by looking at window.location.hash. Use substring(1), to return everything after the # in the window.location.hash value.
if(window.location.hash) {
$('a[name=' + window.location.hash.substring(1) + ']').next('.news_content').show();
} else {
$('.news_content').first().show();
}
I solved the problem.
First: I ned to use nextAll() as many of you said.
Second: I included a CSS with jQuery (one that's only used when JS is enabled). I had to include this before the $(document).ready function. Else it was setting the news_content elements to display:none
Thanks to all who tried to help me.
All the answers have simlilar variations for hash, but none check to see if the hash has a matching element:
I suggest checking that the element exists as part of condition.
var contentToDisplay=$('.news_content').first();
if(anchor[1]){
var $link= $('a[name="' + anchor[1] + '"]');
contentToDisplay= $link.length ? $link.next().next('.news_content') : contentToDisplay;
}
contentToDisplay.show()

How to properly do JS condition?

I run this jQuery (1.8.3) code and always get the "in" alerted even when the length is greater than 1.
What I'm doing is dynamically adding elements to a menu and the if is to make sure this element doesn't exist yet.
I tried also == 0 and === 0 but the result is the same...
Here is a JS fiddle: http://jsfiddle.net/mHhwq/4/
$(".sidebarit a.olink").click(function(event){
iframe_url = $(this).attr("href");
sidebar_id = '#' + iframe_url.replace(/[/.]/g, '');
alert('sidebar_id: ' + sidebar_id);
// create the sidebar if it doesn't exist
if ($(sidebar_id).length < 1) {
alert("in");
$("#sidebar_nav ul").append('<li></li>');
$("#sidebar_content").append('<div id="' + sidebar_id + '" style="display:none;"></div></div>');
} else { alert("out"); }
// don't follow the link
event.preventDefault();
});
In FireBug I see the length equals 1 but still enters the block.
What am I doing wrong?
Update:
My mistake was that I added the # at the wrong place...
Try to put alert inside if stmt as alert($(sidebar_id).length).
And you are making a mistake in appending the div to$("#sidebar_content").
Where sidebar_id is something like #test from sidebar_id = '#' + iframe_url.replace(/[/.]/g, ''); and you are appending like <div id= "#test" there, where it should be <div id= "test"(No # symbol is requird for id).
Your code will results like
$("#sidebar_content").append('<div id="#test" style="display:none;"></div></div>');
Change to
$("#sidebar_content").append('<div id="test" style="display:none;"></div></div>');
Then try again.
You must not have more than one element with the same ID. jQuery takes just the first in such a case.
To prove this have such HTML:
<div id="mydiv">hello</div>
<div id="mydiv">world</div>
Then this code:
var myDiv = $("#mydiv");
alert("length: " + myDiv.length + ", contents: " + myDiv.html());​
Test case.
If you have more than one element you need to iterate, use class instead or alternatively make sure to have unique ID for each sidebar and take the one closest to the clicked element.

How to select for something that begins with a string but doesn't end with a different string in jQuery?

I am new to jQuery, exploring its syntax a bit.
My page has elements like this:
<area id="SA" ... />
<area id="AF" ... />
<area id="EU" ... />
<area id="NA" ... />
I am trying to show and hide div sections based on click events off the area tags, which have matching ending ID's, coded like this:
<div id="div_SA" ... />
<div id="div_AF" ... />
<div id="div_EU" ... />
<div id="div_NA" ... />
So, to show the exact match, but hide all the div sections which have id's that start with "div_" but don't otherwise match, without hiding every other div on the page, I tried this:
var q = 'div[id="div_' + event.target.id + '"]';
var r = 'div[id^="div_"],div:not[id$=' + event.target.id + '"]';
$(q).show();
$(r).hide();
$(r).hide(); is not working. What am I doing wrong? (I know I could assign CSS classes and get at them with class names, but I'm still curious about how to construct a query that will work this way.)
Make things as easy and simple as possible, since you are new at jQuery, you should get the habit of using on(). Not click(), that is outdated, and simply just refers to the on method.
$('area').on('click', function() {
var id = "#div_" + $(this).attr('id'), // comma allows you to make multiple variables
divs = $('div').hide() // puts all the divs in a variable and automatically hides them all
// filter through all the divs, and selects the one with the id,
// of the area that was clicked, and shows it
divs.filter(id).show();
});​
Hope this could help you for now. If not, please let me know.
Edit: See below for the syntax fix as mentioned in your post,
var q = '#div_' + this.id;
var r = 'div[id^="div_"]:not("#div_' + this.id + '")';
$(r).hide();
$(q).show();
DEMO
Please check the alternate solution below,
For evaluating q, I would simply use
var q = $('#div_' + this.id);
And for r,
var r = $('div[id^="div_"]').not(q);
r.hide();
q.show();
DEMO
The not css pseudo selector uses parenthesis not brackets. Also you have an unmatched quotation mark towards the end before the last bracket.
var r = 'div[id^="div_"],div:not(#' + event.target.id + ')';
Also, your code can be simplified by changing it to:
var q = '#' + event.target.id;
var r = 'div[id^="div_"]:not(#' + event.target.id + ')';
$(q).show();
$(r).hide();
How about this:
$('area').click(function() {
var areaID = $(this).attr('id');
$('div[id^="div_"]').hide();
$('div[id^="div_' + areaID + '"]').show();
});​
//start by selecing all of the DIV elements that have an ID attribute that starts with "div_",
//and hide all of them,
//then filter that list down to only the element(s) that have an ID that ends with the id of the `event.target` element
//and show that/those element(s)
$('div[id^="div_"]').hide().filter('#div_' + event.target.id).show();
Short and simple
// cache divs, no need to search them again
var divs=$('div[id^="div_"]');
$('area').click(function(){
divs.hide().eq( $(this).index() ).show();
});

Does jQuery have an equivalent to Prototype's Element.identify?

Is there a built in method or defacto default plugin that will let you automatically assign an unique ID to an element in jQuery, or do you need to implement something like this yourself? I'm looking for the jQuery equivalent to Prototype's identify method
Here's an example. I have some HTML structure on a page that looks like this
<span id="prefix_1">foo bar</span>
...
<div id="foo">
<span></span>
<span></span>
<span></span>
</div>
I want to assign each of the spans an ID that will be unique to the page. So after calling something like this
$('#foo span').identify('prefix'); //fake code, no such method
The rendered DOM would look something like this
<span id="prefix_1">foo bar</span>
...
<div id="foo">
<span id="prefix_2"></span>
<span id="prefix_3"></span>
<span id="prefix_4"></span>
</div>
Is there anything official-ish/robust for jQuery, or is this something most jQuery developers roll on their own?
jQuery.fn.identify = function(prefix) {
var i = 0;
return this.each(function() {
if(this.id) return;
do {
i++;
var id = prefix + '_' + i;
} while($('#' + id).length > 0);
$(this).attr('id', id);
});
};
$('span').identify('test');
Tested this on:
<span id='test_2'></span>
<span>test1</span>
<span>test2</span>
<span>test3</span>
Turned it to:
<span id="test_2"></span>
<span id="test_1">test1</span>
<span id="test_3">test2</span>
<span id="test_4">test3</span>
Not that I know of, but you could do this yourself by adding the id attribute and supplying a GUID.
To add the attribute:
$(foo).attr( "id", createGuid() );
For the createGuid() implementation, see this question.
Note that you could easily turn this into a jQuery plug-in so that this function (you could even name it identify()) is available on any $-expression.
Based on Paolo's solution:
jQuery.fn.identify = function(prefix) {
var i = 0;
return this.each(function() {
if($(this).attr('id')) return;
do {
i++;
var id = prefix + '_' + i;
} while($('#' + id).length > 0);
$(this).attr('id', id);
});
};
$('span').identify('test');
A small change that will avoid to re-count already used ids.
I'd modify the given function slightly and make it:
jQuery.fn.identify = function(prefix) {
var i = 0;
return this.each(function() {
if($(this).attr('id')) return;
do {
i++;
var id = prefix + '_' + i;
} while(document.getElementById(id) != null);
$(this).attr('id', id);
});
};
ID's could contain special characters that would require escaping in order to work properly with jQuery's CSS selector engine--like ".". So instead of finding them and escaping them, it's simpler and faster to replace it with the document method.
Maybe try
$("#foo span").each(function(){
$(this).attr("id", "prefix_" + $(this).parent().index($(this)));
});

Categories