using classList to check for class in body - javascript

I'm trying to create a test that checks the body of a webpage for a particular class using vanilla JS
currently my code looks like this
var whole = document.getElementsByTagName("body")[0];
whole.classList.contains("desiredClass");
this returns "false" on a class even though it exists in my body.
I have attempted to redefine whole as
var whole = document.body
and received the same result
Question: what is my code missing? I felt this was a pretty straightforward test, but I am certainly missing something
EDIT:
My classList function works, but was not searching for DIV classes within the body.
How do I narrow the search within the document.body to search all div classes?

It's not good to findElementByTagName in this case. Using the document.body instead is much better.
Anyway, your code seems to be ok. Maybe it's browser compatibility issue?
Here you can see which versions of browsers supports classList property of DOM element: classList doc
You can use this solution. It is much certain.
var classes = document.body.getAttribute('class').split(' ');
var contains = classes.indexOf('desiredClass') > -1;

Related

Why content within a header element can be accessed with .text and content within a p element with innerHTML in JavaScript

If I have the following html
<h2 id="myheader">some content</h2>
<p id="myp">some content </p>
To get the content of the header, I can do
document.getElementById('myheader').text
But then I was trying the same logic with the paragraph element, but instead I had to use innerHTML
Is there some sort of logic behind this difference?
Also in the console I like the fact that I can write something like window and then I can drill down all the available methods that I can use after window. For example that's how I found what window.document is the same as document. Is there a way to do the same thing for things like document.getElementById('myheader'), a way to investigate what methods are available after the dot document.getElementById('myheader').HERE just to learn by experimenting
EDIT: I realise that I am wrong about .text. There must be something wrong with my code (even though I can't see it), sorry for any confusion, if you think it should be edited not to mislead anyone, please do
Thanks
textContent is available for both elements (H1 and p).
You can examine an HTMLElement like this:
var elem = document.getElementById(some_id),
s = [],
key;
for (key in elem) {
s.push(key + ': ' + elem[key]);
}
s = s.join('\n');
console.log(s);
Many consoles create also a tree of the element structure just by logging an element:
console.log(document.getElementById(some_id));
Can you really do document.getElementById('myheader').text? Because it doesn't seem to me, unless you are using the jQuery .text() method.
In any case, you can methods such as innerText and textContent on both of your elements.
The reasons why window.document is the same as document is because document is a variable in the global scope, which is the window scope.
Also, to investigate which methods are available inside the console, you might assign your element to a variable, and then you can see the autocomplete, at least in Chrome developer tools.
var el = document.getElementById('myheader')
Then start typing el. … in the console.
According to MDN, there's no such thing as a .text property on HTMLHeadingElement. I've tested this on Chrome, just to be sure:
> document.createElement('h2').text
undefined
To reliably get the text content from any element you can use this construct:
var text = element.textContent || element.innerText || '';
Here, .textContent is understood by most browsers, whereas .innerText is specific to IE and '' is the fallback value.

How to get HTML node object and not the HTML itself with JavaScript

When I do
var el = document.querySelector('.some-class');
I get the plain HTML.
How then do I get access to the Javascript node element?
I can see it when I do dir(el) in the console.
This is the dom itself. You can manipulate the element with only this. Why it is showing the HTML, it is just a common way that the console shows you. If you want to add a class for example, you can do.
var el = document.querySelector('.some-class');
el.classList.add('test')
This will work as it should. If you want to HTML of the element, you could also do:
el.outerHTML
Hope this helps you.
Actually, document.querySelector() returns an element object, which implements the Element interface which inherits from the Node interface.

Strange ie behaviour with jquery inArray

Hello this seems to be working on IE8 :
var clsName = link.parents("div.fixed_column").attr("class").split(" ");
if($.inArray("column_one", clsName)
While this one reports error (Object expected errror in jquery).
var clsName = link.parents("div.fixed_column").attr("class");
What is the right way to do this? I thought purpose of inArray was that jquery will handle cross browser issues.
Unfortunately, this is indirectly answering your question, but... You seem to be looking to detect if an element has a class, and since you're already using jQuery, just use the hasClass method - http://api.jquery.com/hasClass/
For your specific code, try:
if (link.parents("div.fixed_column").hasClass("column_one")) {
// It has the "column_one" class
}
The more immediate answer to your question is that link.parents("div.fixed_column").attr("class") returns a single string. When the jQuery selector (div.fixed_column) returns multiple elements, which is very possible when using classes, using jQuery methods that get information (like .attr, using one parameter...to "get" the value) return the first matched element's value only.
So say the selector matches 3 elements:
["<div id='div30' class='fixed_column div30_class'></div>",
"<div id='div2' class='fixed_column div2_class'></div>",
"<div id='div17' class='fixed_column div17_class'></div>"]
Then the value returned from .attr("class") will be: fixed_column div30_class because it's the first matched element.
I'm not sure, but I think you're expecting jQuery to return an array of all the matched elements' values, which it just doesn't. So that doesn't mean jQuery isn't handling cross-browser issues, it just means you need to look up what the method does/returns.
I could've sworn that jQuery 2.0 has options for doing what you want - directly from calling the getters (or something similar), but I can't find it anymore :( Maybe I'm remembering incorrectly. Anyways, you could easily use $.each and/or $.map to look at every matched element, but it depends on what you were really trying to do with it.
You can't read the attributes of multiple elements into an array with .attr("class"). But why don't you just target the desired class in the selector like this?
var cols = link.parents("div.fixed_column.column_one");
Then change your conditional to check for an empty set:
if(cols.length) { ...

Assigning DOM style to var

For some reason if I type in:
var i = document.getElementById('fake').style.backgroundPosition;
I get undefined.
However,
document.getElementById('fake').style.backgroundPosition;
by itself, returns the right answer.
Any ideas?
When I use that line of code on an element that actually exists in Chrome, I get i equal to an empty string. You can see that here in this jsFiddle: http://jsfiddle.net/jfriend00/b6syd/.
So, if you are getting undefined, then probably your object "fake" doesn't exist when you're running the code.
element.style.backgroundPosition will only return to you an actual inline style settings or programmatically values set for that particular object directly. It won't return computed styles from stylesheets. If you want to get the current style setting for that attribute, then you need to use something like this:
var i = window.getComputedStyle(document.getElementById('fake'), null).getPropertyValue('background-position');
And, it's different in IE. This is where a framework like jQuery or YUI is very useful.
In jQuery, it would just be this:
var i = $("#fake").css('backgroundPosition');

$(this) OR event.target OR var input = $(this)

jQuery is currently providing me with a fun introduction to Javascript after 12 years of surviving happily without. I'm at the stage where I'm trying to learn as much as I can about optimising the code I write and, whilst I have found plenty of good reference material, there is something quite basic which is puzzling me and I have been unable to find anything about it anywhere.
When I'm attaching something to an element how should I be referring to that element within the function. For example, when attaching a function to an element's click event :
$('#a_button',$('#a_list_of_buttons')).click(function() {
// NOW WHAT'S THE BEST WAY TO REFER TO '#a_button' ?
});
I know not to keep re-selecting it like so as the browser has to search the whole DOM again from scratch to find what it's already found once :
$('#a_button').click(function() {
// I KNOW THAT THIS IS NAUGHTY
var buttonValue = $('#a_button').val();
$('#a_button').addClass('button_has_been_clicked');
});
Currently I'm using either of the following but am not entirely sure what each is actually doing :
$('#a_button').click(function() {
// USING this
var buttonValue = $(this).val();
$(this).addClass('button_has_been_clicked');
});
But is this just re-selecting like in the first "naughty" example?
$('#a_button').click(function(event) {
// USING event.target
var buttonValue = $(event.target).val();
$(event.target).addClass('button_has_been_clicked');
});
This seems like it might be better but is it efficient to refer to 'event.target' multiple times?
$('#a_button').click(function(event) {
// USING A LOCAL VARIABLE
var thisButton = $(this);
// OR SHOULD THAT BE
var thisButton = $(event.target);
var buttonValue = thisButton.val();
thisButton.addClass('button_has_been_clicked');
});
I understand the performance efficiencies of passing things to variables but I'm unsure whether or not in these situations using $(this) or $(event.target) provides me with the same efficiencies already and so by setting a new variable I'm actually doing more work that I need to.
Thank you.
this and event.target are not always the same.
this refers to the element you assigned the listener to ( in this case the '#a_button' ). event.target however is the element that actualy triggered the event, which can be a childnode of #a_button.
So $(this) is the thing you are looking for.
See reference: http://api.jquery.com/event.target/
I may be wrong, but this and event.target are both just different references to the same element.
this and event.target are not always references to the same element. But in answer to your question, var thisButton = $(this); is definitely the winner. If you were writing C# code, you would never do the following:
this.Controls[0].Controls[0].Text = "Foo";
this.Controls[0].Controls[0].Controls.Clear();
You would do this:
var control = this.Controls[0].Controls[0];
So you probably should never re-use $(this) more than once either. Althought it's trivial to convert this from a DOM element to a jQuery object, it's still an unnecessary overhead.
However, sometimes you need to gear back from optimisation to make sure your code maintains it's readability.
Another option of course is just to change what this is. This is javascript afteral:
this = $(this); // Now `this` is your jQuery object
Disclaimer: I only just tried the above and it seemed to work. Might have some issues though.
I built a little example to demonstrate how this and e.target actually work: http://jsfiddle.net/xZAVa/
In my experience i would go with the following:
$('#a_button').click(function() {
// USING this
var buttonValue = $(this).val();
$(this).addClass('button_has_been_clicked');
});
The this in the context of your click callback method is a reference to the DOM event. Since you already have a reference to the DOM object it is trival to convert it into a jQuery object since a lookup is not required.
But on a side note, if you don't need to use jQuery in your callback, then don't. You can simply get the value of the button using standard JS this.currentTarget.value.
The other examples you mentioned require a DOM lookup, and depending on the complexity of your selector can take longer. Using a id based lookup like '#a_button' will perform better than a class based looked like .myClass.

Categories