I have a page with div's that each have multiple classes.
<div class='publication parent20'></div>
<div class='publication parent12 parent42 parent91'></div>
<div class='publication parent20'></div>
<div class='publication parent32 parent23'></div>
I need a function that takes a class passed to it as a variable, sets they style of all divs with publication class to none and then sets tags with the specified class.
function swap_pub(pub){
document.getElementById("publication").style.display = "none";
//set style.display = "block" to all elements with class = pub
}
any thoughts on how I would do this.
Use getElementsByClassName()MDN
var pubs = document.getElementsByClassName('publication'); // a NodeList
for (var i = 0; i < pubs.length; i++) {
pubs[i].style.display = 'block';
}
This is how it looks using jQuery:
$('.publication').show(); // concise
There is also querySelectorAll which is slightly more widely supported than getElementsByClassName.
function setDisplay(className, display) {
var items = document.querySelectorAll('.' + className);
var i = items.length;
while (i--) {
items[i].style.display = display;
}
}
Related
How can this jQuery-dependent code
$('.myElement').click(function () {
drawMode = !drawMode;
$icon = $(this).children('i');
if (drawMode) {
$icon.removeClass('a').addClass('b');
} else {
$icon.removeClass('b').addClass('a');
}
});
be rewritten into native javascript?
I have tried
var element = document.getElementsByClassName('myElement')[0];
element.addEventListener('click', function (e) {
drawMode = !drawMode;
var icon = this.children()[0];
if (drawMode) {
icon.classList.remove('a').add('b');
} else {
icon.classList.remove('b').add('a');
}
});
but I cannot find the children element correctly.
jQuery's children allows you to filter by selector, something that isn't in the DOM API (you can find all descendants matching a given CSS selector, but you can't [for now] limit it to just children).
If it doesn't matter whether it's a child or just any descendant, then:
var icon = this.querySelector("i");
That finds the first descendant within the element that's an i element. I suspect that would work just fine for you. The only time it might not would be if you had this:
<div class="myElement">
<span>
<i>You DON'T want this one</i>
</span>
<i>You do want this one</i>
</div>
If that's the case and you need to only look at children, not all descendants, you'll need a loop:
var icon = null;
var n;
for (n = 0; n < !icon && this.children.length; ++n) {
if (this.children[n].tagName.toLowerCase() === "i") {
icon = this.children[n];
}
}
In ES2015+ (you can transpile to use it today), that's so much tidier:
let icon = Array.from(this.children)
.find(child => child.tagName.toLowerCase() === "i");
A few notes:
The add and remove functions of the classList do not return the classList object, so you can't concatenate them (e.add().remove(), like you are used to do in jQuery).
In your code you only go over the first element, while when using jQuery the changes are made for all elements that you selected.
I used the querySelectorAll and filtered out elements that are not direct childs, (checked for the parentElement since you used the children() function of jQuery).
Here is an example:
drawMode = true;
var elements = document.getElementsByClassName('myElement');
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', function() {
var that = this;
drawMode = !drawMode;
var icons = this.querySelectorAll('i');
for (var j = 0; j < icons.length; j++) {
var icon = icons[j];
if (icon.parentElement != that) {
continue;
}
if (drawMode) {
icon.classList.remove('a');
icon.classList.add('b');
} else {
icon.classList.remove('b')
icon.classList.add('a');
}
}
});
}
i.a {
background: red;
}
i.b {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="myElement">
<i>asd</i><br />
<i>fgh</i><br />
<span><i>This element will not change because he isn't a direct child</i></span><br />
</div>
Generally, document.querySelectorAll is very useful when converting jQuery to vanilla javascript.
Returns a list of the elements within the document (using depth-first pre-order traversal of the document's nodes) that match the specified group of selectors. The object returned is a NodeList.
// get a NodeList of elements which match CSS Selector '.myElement'
var elements = document.querySelectorAll('.myElement');
for (var i = 0; i < elements.length; i++ ) {
// loop through every element with class 'myElement'
var element = elements[i];
element.addEventListener('click', function(event) {
drawMode = !drawMode;
var icon = element.querySelector('i');
if (drawMode) {
icon.classList.remove('a');
icon.classList.add('b');
} else {
icon.classList.remove('b');
icon.classList.add('a');
}
});
}
Note I've also used element.querySelector to match descendants of the currently processed element.
I want to get every single ID of every element inside of a Div at once, and change all of their class names. Like:
<div id = "container">
<div id = "alot"></div>
<div id = "of"></div>
<div id = "random"></div>
<div id = "ids"></div>
</div>
<script>
var everyId = //all of the ids in #container. but how ?
document.getElementById( everyId ).className = "anything";
</script>
I've seen solutions using libraries but Is this possible with pure Javascript?
Try something like this:
var ids = [];
var children = document.getElementById("container").children; //get container element children.
for (var i = 0, len = children.length ; i < len; i++) {
children[i].className = 'new-class'; //change child class name.
ids.push(children[i].id); //get child id.
}
console.log(ids);
Leverage document.querySelectorAll() and a loop to achieve what you're looking for:
var everyChild = document.querySelectorAll("#container div");
for (var i = 0; i<everyChild.length; i++) {
everyChild[i].classList.add("anything");
}
JSFiddle
You can leverage querySelectorAll to provide a selector to fetch the elements you are interested in.
var c = document.querySelectorAll("#container > div");
console.log(c); // array of all children div below #container
You can use querySelectorAll for the Child elements within the specified parent:
var a = document.querySelectorAll('#container > div'); // get all children within container
console.log(a);
for (var i = 0; i<a.length; i++){ // loop over the elements
console.log(a[i].id); // get the ids
a[i].className = 'newClass'; // change the class names
}
I have found the following code from stackoverflow:
<script type="text/javascript">
var allTags = document.body.getElementsByTagName('*');
var classNames = {};
for (var tg = 0; tg< allTags.length; tg++) {
var tag = allTags[tg];
if (tag.className) {
var classes = tag.className.split(" ");
for (var cn = 0; cn < classes.length; cn++){
var cName = classes[cn];
if (! classNames[cName])
{
classNames[cName] = true;
}
}
}
}
var classList = [];
for (var name in classNames)
classList.push(name+'<br />');
document.getElementById('allclasses').innerHTML = classList.sort();
</script>
The above works awesome but just for classes, what about ID's
Now there is one scenario that with the div like this:
<div class="head">
internal divs having classes, IDs should be ignored --
</div>
<div class="footer">
internal divs having classes, IDs should be ignored --
</div>
How can i make above changes to the code, I am asking because I am dumb in Javascript, and i need to make it work as task given..
Assuming you just wanted a list if IDs, like your class list, there is a jQuery version.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/LXhtr/
ID Version in jQuery:
var ids = {};
$('[id]').each(function () {
var id = this.id;
ids[id] = id;
});
var idList = [];
for (var id in ids) {
idList.push(id + '<br />');
}
$('#allids').html(idList.sort());
Notes:
$('[id]') is a jQuery selector that returns any element with an id. $('[class]') does the same for any elements with classes. As you can see jQuery is a lot leaner than raw JavaScript. There is still scope to make these even shorter if required, but that would move so far from your existing code you might not recognize anything :)
Update: http://jsfiddle.net/TrueBlueAussie/LXhtr/3/
You wanted to exclude anything within a class="header" or class="footer".
You can do this in jQuery with selectors like :not([class=header]):not([class=header] *) which basically says, do not include this match, or anything beneath this match.
var ids = {};
$('[id]:not([class=header]):not([class=footer]):not([class=header] *):not([class=footer] *)').each(function () {
var id = this.id;
ids[id] = id;
});
var idList = [];
for (var id in ids) {
idList.push(id + ' <br/>');
}
$('#allids ').html(idList.sort());
I'm trying to hide elements by their ids:
document.getElementById('Table1').style.display = 'none';
But there are many divs goes like Table1, Table2, Table3...
So how to use regular expressions in a situation like this?
Set class to all these elements. It was invented for such cases.
HTML:
<div id="Table1" class="myTables"></div>
<div id="Table2" class="myTables"></div>
<div id="Table3" class="myTables"></div>
JavaScript:
var elements = document.getElementsByClassName("myTables");
for (var i = 0, len = elements.length; i < len; i++) {
elements[i].style.display = "none";
}
UPDATE: If setting classes is not applicable in your case, you can always use the modern method querySelectorAll with attribute starts with selector:
var elements = document.querySelectorAll("div[id^='Table']");
for (var i = 0, len = elements.length; i < len; i++) {
elements[i].style.display = "none";
}
DEMO: http://jsfiddle.net/L2de8/
Regural expression will not work in this example.
Either use a common class name on all the elements, or, if you cannot change HTML, you can use Selectors API to select the elements you need to hide.
Use
var allElemsWithIdStartingFromTable = document.querySelectorAll('[id^="Table"]');
to select all elements with ID starting with "Table", so it would be Table1, Table2, but also TableOfProducts, keep that in mind.
Then you need to iterate over this and check if the id attribute matches /^Table\d+$/ regular expression.
for example..if you give myTables as class name for div..use that for lenght..
var elements = document.getElementsByClassName("myTables");//to know the length only..
for(var i=0;i<elements.length;i++)
{
document.getElementById('Table'+i).style.display = 'none';
}
use looping concept..its an example..
I have a function connected to a class, that lets me remove it by className.
the problem I have is when I have two elements with the same class name. the function close both of the classes and not only the one that's selected.
I think that i use use a element.this function, but when I try it, none of the classes removes.
Any ideas ?
function CloseEvent(){
var CloseEvent = "close";
var addClassArr= document.getElementsByClassName(CloseEvent);
for(var i=0; i<addClassArr.length; i++){
var addClass = addClassArr[i];
addClass.addEventListener("click", closebutton, true);
}
function closebutton() {
var classToRemove = "dice-window-wrapper";
var elems = document.getElementsByClassName(classToRemove);
for (var i = 0; i < elems.length; i--) {
elems[i].parentNode.removeChild(elems[i])
}
}
}
CloseEvent();
the function close both of the classes and not only the one that's selected.
That's wrong, since more than one are selected via document.getElementsByClassName - and all of them are removed correctly.
Instead of selecting elements by their class name, select the one on which the event was fired at.
function closebutton(e) {
var elem = e.target; // or just the "this" keyword
// elem is the <div class="close" />
var wrapper = elem.parentNode.parentNode;
// wrapper is the <div class="dice-window-wrapper" />
wrapper.parentNode.removeChild(wrapper);
}
Updated the html code to reflect the html used on your site.
<div class="dice-window-wrapper">
<div class="dice-menubar-wrapper">
<div class="close">
close one
</div>
</div>
</div>
<div class="dice-window-wrapper">
<div class="dice-menubar-wrapper">
<div class="close">
close one
</div>
</div>
</div>
then here is how to remove the clicked element:
function CloseEvent(){
var CloseEvent = "close";
var addClassArr= document.getElementsByClassName(CloseEvent);
for(var i=0; i<addClassArr.length; i++){
var addClass = addClassArr[i];
addClass.addEventListener("click", closebutton, true);
}
function closebutton(e) {
var classToRemove = " "+"dice-window-wrapper"+" ";
var obj=e.target;
while((" "+obj.className+" ").indexOf(classToRemove)==-1){
obj=obj.parentNode;
}
if(obj.tagName.toLowerCase()!="div"){
console.log("something wrong in closebutton");
return;
}
obj.parentNode.removeChild(obj);
}
}
Note that this doesn't work at all in IE8 because getElementsByClassName is not supported not is the event passed in this way and there might be a problem with addEventListner. That's why I usually use jQuery.
You should be able to identify the object calling a JS function by using this to identify the triggering element like
function closebutton() {
this.parentNode.removeChild(this);
}
e.g. Delete the SO logo!
function notSO(){this.parentNode.removeChild(this);}
document.getElementById("hlogo").addEventListener("mouseover", notSO, true);
Here's your modified code:
function CloseEvent(){
var CloseEvent = "close";
var addClassArr= document.getElementsByClassName(CloseEvent);
for(var i=0; i<addClassArr.length; i++){
var addClass = addClassArr[i];
addClass.addEventListener("click", function(){ closebutton(this) }, true);
}
function closebutton( elem ) {
var classToRemove = "dice-window-wrapper";
//var elems = document.getElementsByClassName(classToRemove);
//for (var i = 0; i < elems.length; i--) {
// elems[i].parentNode.removeChild(elems[i])
//}
// you have passed the element to be removed, directly remove it
elem.parentNode.removeChild(elem);
}
}
CloseEvent();