Hopefully I can explain it well enough. I do
var foo = document.getElementsByTagName('bar');
var len = foo.length;
for(var i=0;i<len;i++){
//Do stuff
}
Inside that for I also want to be able to get an element (specifically a class) that is buried deep within foo[i]. My thought is something like
var whatIWant = document.getElementsByClassName("name").foo[i];
but that doesn't seem to be what I need to do. Am I just not sure on the syntax or do I need to do something completely different?
You've almost got it:
foo = document.getElementsByTagName('bar');
// foo is now a nodelist of all nodes named 'bar'.
for (i = 0; i < foo.length; i++) {
bar = foo[i].getElementsByClassName('baz');
// bar is now a nodelist of all elements with class 'baz' in the dom tree under foo[i].
}
If you were using jquery, it'd be as simple as:
$('bar .baz').each(function() {
$(this). etc...;
});
As far as I'm aware getElementsByClassName is HTML5 (according to this: https://developer.mozilla.org/en/DOM/document.getElementsByClassName) and so using it means that not all browser will support it.
When you grab an Element from the dom, like with document.getElementsByTagName, you get the same method getElementsByTagName and so you can do:
foo[i].getElementsByTagName("...")
For the collection of desired elements, then you can iterate over that array and search for the matching classes.
Also, I recommend using javascript libraries such as jQuery or MooTools, it will make your life easier.
Related
why when i write
document.getElementByClass('home1').setAttribute('style', 'background-image:url(img/red_menu.PNG);');
it doesn't work?
i have the element with class="home1"
with document.getElementById('home1')...
works fine
thanks
It's getElementsByClassName, not getElementByClass; details here. Note that IE does not support this function (yet).
getElementsByClassName returns a NodeList of matching elements (rather than a single element), so:
var list, index;
list = document.getElementsByClassName("home1");
for (index = 0; index < list.length; ++index) {
list[index].setAttribute(/* ... */);
}
For this sort of thing, you may want to use a library like jQuery, Prototype, Google Closure, etc., to pave over the various browser differences for you. They can save you a lot of time and trouble compared with dealing with those differences yourself.
For instance, in jQuery:
$(".home1").attr(/* ... */);
...applies that attribute (via jQuery#attr) to every element with the class "home1". Although in your particular case, you'd probably want jQuery#css instead.
If you have only one classname in your entire HTML file, then you could also use
document.getElementsByClassName('navbar-nav')[0].setAttribute('id', 'navbar-toggle');
I'm working on a challenge that requires us to use Underscore and JQuery to make changes to the DOM, but the second part of the challenge is requiring us to use Javascript browser utilities to do the same thing.
We are given an Array, and asked to manipulate the data and append the result to the DOM. I did that using the _.each method and $().append. For the second part, I am using the Javascript forEach() method to manipulate the data, but how do I use javascript utilities to append the resulting variable to the DOM with without jQuery?
Select the container, iterate the array with a for loop or forEach method, create elements and append them.
var arr = ["Alice", "Bob"]
var ulEl = document.querySelector("ul");
for (var i = 0; i < arr.length; ++i) {
var li = document.createElement("li");
li.innerHTML = arr[i];
ulEl.appendChild(li);
}
<ul>
</ul>
Instead of using the jQuery library, its possible to manipulate the DOM using vanilla JavaScript functions. In particular, take a look at some of the functions in the DOM API like document.querySelector
With jquery, I've got the following code:
$('a[data-hello]').click(function(){ = That select all "a" elements with "data-hello".
I'm trying to make this with raw Javascript. I stop here:
document.querySelectorAll("data-hello").onclick = function() {
(btw, theres a way to select all the A elements with data-hello and not all with data-hello? o.O)
But querySelectorAll returns a Array. Because of this, it only works if I determine a position. This way:
document.querySelectorAll("data-hello")[5].onclick = function() {
But I want ALL ELEMENTS, not specific elements, like with jQuery. I cant use jQuery.
It is so simple with Jquery :( I must make a "for" to wade through all the positions in JS? Is this necessary? sorry I do not understand...
What I want to do:
I want to get the data attribute value of the element that is clicked. I use this for this inside the function and, then, I applied another function that add a class in a specific element.
Basically, there is buttons with classes in data attribute value. This classes will be applied to a specific element.
Put the array (actually a NodeList) of elements in a variable and loop through them to set the event handler on each of them. That's what the jQuery methods do to apply something to all elements in a jQuery object. There is no way around the loop, with jQuery it's just hidden within the methods. You can use the same selector syntax as in jQuery with querySelectorAll.
var arr = document.querySelectorAll("a[data-hello]");
var f = function() {
// do something
};
for (var i = 0; i < arr.length; i++) {
arr[i].onclick = f;
}
querySelectorAll accepts a string of comma-separated CSS selectors, just like jQuery, so you can give it the same string: 'a[data-hello]'.
The difference between native and jQuery that you are running into is in calling methods on the elements returned. jQuery returns a jQuery object, which has methods that often loop over all the elements, .click() being one such methods. You need to replicate that with the array of elements that querySelectorAll is returning by looping over the array and applying the same handler to each element's onclick property.
Try this:
var myElements = document.querySelectorAll("a[data-hello]");
Array.prototype.forEach.call(myElements, function (element) {
element.onclick = function () {
// Your onclick handler code goes here.
console.log('clicked', element);
};
});
as simple as that:
var dataElems = document.querySelectorAll("[data-hello]")
for (var i=0;i<dataElems.length;i++) {
dataElems[i].onclick = function(i,v) {
alert(this.innerHTML)
}
}
example http://jsfiddle.net/acrashik/W86k8/
I'm trying to do three things onclick:
have element with id="notes_content" change display:none to display: block
have element with id="oct" change width = "1190px" to width = "550px"
have elements with class="oct_days" change width = "168px" to width = "73px"
Fiddle of full code: http://jsfiddle.net/ascottz/jX3wh/
The first two happen, but the third does not. I suspect it is a syntax error, but can't catch it myself.
getElementsByClassName returns an array of dom elements, it is not a single instance. You must loop over the array and style each element.
Have a look at the updated fiddle.
for( var i = 0; i < days.length; i++ ){
days[i].style.width = "73px";
}
http://jsfiddle.net/jX3wh/4/
document.getElementsByClassName returns somewhat an array of elements, so you cannot simply refer to it as a DOM element in hope that it will work as you refer to each element of the collection (that is possible in jQuery, btw), so you have to use the foreach loop (doesn't matter how are you gonna achieve this -- via simple for(), or for(x in y), or any other way).
I usually use Array.forEach function, but the specific type of an array returned by the document.getElementsByClassName does not have such function in prototype, so you have to use [].forEach.call(inWhat,function(what){}) syntax, or fallback to for(...) syntax.
Check out this: http://jsfiddle.net/jX3wh/1/
Dunno if it works.
Also, what the f is this???
<div onclick="javascript:showDiv();" class="oct_days">
I am really very surprised this works. You should use onclick="showDiv()" instead, I think.
Somebody, please, tell me how does it work!
Libraries I've seen have DOM wrappers that inclusively handle only the first element of the list in some case, like:
return this[0].innerHTML
and use the whole list in some other like:
for( var i=0, l=this.length; ++i<l; ) this[i].className = cls;
return this
Why is this approach accepted?
I think singling out the first element defeats the purpose of having methods that apply the same thing on the rest of the list. Isn't it bad to have dubious functions? I know it suits many people..but it feels inconsistent and I'm interested in why this is accepted so widely.
EDIT as an example:
jQuery.html()
If the selector expression matches more than one element, only the
first match will have its HTML content returned.
why not all?
the hide() method in bonzo, from Dustin Diaz
//...
hide: function () {
return this.each(function (el) {
el.style.display = 'none'
})
}
why not only the first?
The accessor methods in jQuery return single values because it's simpler and more generally useful. If the .html() API were to return the value if innerHTML for all elements, that'd mean it'd have to return an array. That, in turn, would mean that in the most common case of wanting the contents of a single element, you'd have to add the array access. There's also the problem of knowing exactly which returned value goes with which selected element. In other words, if .html() returned an array of element contents:
var contentList = $('.someClass, span, .hidden .container').html();
If "contentList" were just a simple array, what use would it be? How would the code know for each element which DOM node it came from? Of course there are solutions to this, but again the simple case is made complicated in order to support a rare general case.
It's possible of course to get the list yourself with .map(). I think this is just an issue of smart, practical, pragmatic API design.