Javascript toggle visibility multiple divs - javascript

http://blog.movalog.com/a/javascript-toggle-visibility/
this is a page with some code and a script im using in my site for an image gallery, however when trying to toggle the visibility of multiple div's it only works on the first. can someone please fix it to work with multiple div's, i dont know js :)
here is the javascript
<script type="text/javascript">
<!--
function toggle_visibility(id) {
var e = document.getElementById(id);
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
//-->
</script>
and here is the html code for the links
<tr><td>New York</td>
<td><a href="#" onclick="toggle_visibility('photoshop');">Photoshop Work</td>
<td><a href="#" onclick="toggle_visibility('photography');">Photography</td></tr>
<tr><td><a href="#" onclick="toggle_visibility('art');">Art Projects</td></tr>
wait a sec, could this not be working because it is trying to acess the properties of multiple divs via the "id" property, would it work with the class property and if so would i just change the java script where it says "id" to "class"

It seems that you were trying something like
<div id="a"></div>
<div id="a"></div>
toggle_visibility('a');
The problem is that each id must be unique in the document, so document.getElementById returns a single element, not a collection of elements.
Then, if you want to have more than one element with the same id, you should use classes instead.
<div class="a"></div>
<div class="a"></div>
function toggle_visibility(cl){
var els = document.getElementsByClassName(cl);
for (var i = 0; i < els.length; i++){
var s = els[i].style;
s.display = s.display === 'none' ? 'block' : 'none';
}
}
toggle_visibility('a');
If you want to make it work with multiple classes, use
var toggle_visibility = (function() {
function toggle(cl) {
var els = document.getElementsByClassName(cl);
for(var i = 0; i < els.length; i++){
var s = els[i].style;
s.display = s.display === 'none' ? 'block' : 'none';
}
}
return function(cl) {
if (cl instanceof Array){
for(var i = 0; i < cl.length; i++){
toggle(cl[i]);
}
} else {
toggle(cl);
}
};
})();
toggle_visibility('myclass');
toggle_visibility(['myclass1','myclass2','myclass3']);

You can use
function toggle_visibility(id) {
function toggle(id){
var el = document.getElementById(id);
el.style.display = el.style.display==='none' ? 'block' : 'none';
}
if(id instanceof Array){
for(var i=0; i<id.length; ++i){
toggle(id[i]);
}
}else{
toggle(id);
}
}
And call it like
toggle_visibility('myid');
toggle_visibility(['myid1','myid2','myid3']);
Another possible way is using arguments variable, but that could slow down your code
function toggle_visibility() {
function toggle(id){
var el = document.getElementById(id);
el.style.display = el.style.display==='none' ? 'block' : 'none';
}
for(var i=0; i<arguments.length; ++i){
toggle(arguments[i]);
}
}
And call it like
toggle_visibility('myid');
toggle_visibility('myid1','myid2','myid3');
If you don't want to create the function toggle each time you call toggle_visibility (thanks #David Thomas), you can use
var toggle_visibility = (function(){
function toggle(id){
var el = document.getElementById(id);
el.style.display = el.style.display==='none' ? 'block' : 'none';
}
return function(id){
if(id instanceof Array){
for(var i=0; i<id.length; ++i){
toggle(id[i]);
}
}else{
toggle(id);
}
};
})();
toggle_visibility('myid');
toggle_visibility(['myid1','myid2','myid3']);
Or
var toggle_visibility = (function(){
function toggle(id){
var el = document.getElementById(id);
el.style.display = el.style.display==='none' ? 'block' : 'none';
}
return function(){
for(var i=0; i<arguments.length; ++i){
toggle(arguments[i]);
}
};
})();
toggle_visibility('myid');
toggle_visibility('myid1','myid2','myid3');

You either need to cycle through a list of ids or use a class name as the argument to toggle_visibilty ---- which means you would have to edit the function. It looks like right now you are only calling toggle_visibility on one element.
jQuery makes this kind of thing easier:
<code>
//selects all elements with class="yourClassName"
jQuery(".yourClassName").toggle();
//select all divs
jQuery("div").toogle();
//select all divs inside a container with id="myId"
jQuery("#myId > div").toggle();
</code>

There is a very silly mistake in your code..
Add the id attribute in the td tags id='nyc', etc. and it should work fine

Related

Any better way to hide multiple elements at once?

This works perfectly fine, but for future reference I would like to know if there is a better way to do this.
document.getElementsByTagName('h1')[0].style.display = 'none';
document.getElementsByTagName("p")[0].style.display = 'none';
document.getElementsByTagName("p")[1].style.display = 'none';
document.getElementsByTagName("ul")[0].style.display = 'none';
document.getElementsByTagName("hr")[0].style.display = 'none';
I'm open to using jQuery if it would help.
While jQuery wasn't specifically requested, it would be the shortest implementation to meet the OP's sample code exactly as written:
$('h1:eq(0), ul:eq(0), hr:eq(0), p:lt(2)').hide();
Keep your nodes in an Array, then you can write some functions which will hide or show a whole Array (or NodeList) at once, e.g.
function display_none(nodelist) {
var i = nodelist.length;
while (i-- > 0)
nodelist[i].style.display = 'none';
}
function display_default(nodelist) {
var i = nodelist.length;
while (i-- > 0)
nodelist[i].style.display = '';
}
So you have
var elms = [
document.getElementsByTagName('h1')[0],
document.getElementsByTagName("p")[0],
document.getElementsByTagName("p")[1],
document.getElementsByTagName("ul")[0],
document.getElementsByTagName("hr")[0]
];
Now can simply do
display_none(elms); // hide them all
display_default(elms); // return to default
Here's a pure Javascript option that implements a jQuery-like extension for the :lt(n) pseudo selector so you can specify however many of each tag you want.
As the question asked, this operates on the first two "p" tags, then the first "h1", "ul" and "hr" tags:
function hideItems(selector) {
var r = /:lt\((\d+)\)/;
selector.split(',').forEach(function(item) {
var len, elems, i, m = item.match(r);
if (m) {
item = item.replace(r, "");
elems = document.querySelectorAll(item);
len = Math.min(+m[1], elems.length);
} else {
elems = document.querySelectorAll(item);
len = elems.length;
}
for (i = 0; i < len; i++) {
elems[i].style.display = 'none';
}
});
}
hideItems('p:lt(2),h1:lt(1),ul:lt(1),hr:lt(1)');
Working demo: http://jsfiddle.net/jfriend00/m9vspymz/
Using Pure JavaScript
//gets all DOM elements with a tag of p or li
var elems = document.querySelectorAll('p,li');
//loops over all elements
for(var i = 0;i < elems.length; i++)
{
//hides each element in the array
elems[i].style.display = 'none';
}
Code Specifically for you
var elems = document.querySelectorAll('p,h1,ul,hr');
for(var i = 0;i < elems.length; i++)
{
elems[i].style.display = 'none';
}
Here's the code (JavaScript):
var n = [ // 'tagname',which in order
'h1',0,
'p',0,
'p',1,
'ul',0,
'hr',0
];
for(var i = 0;i < elems.length)
{
document.getElementsByTagName(n[i*2])[(n[i*2]+1)].style.display = 'none';
i++;
i++;
}

expanding and collapsing folders

I need to get more than one element to toggle open and closed. Right now the function is just selecting the ID, but I'd like to know how to get it to select a class. I thought I could change the document.getElementById to document.getElementByClass but that didn't work.
I picked this bit of code during my search:
#ToggleTarget {display:hidden;}
<script type="text/javascript">
function Toggle() {
var el = document.getElementById("ToggleTarget");
if (el.style.display == "block") {
el.style.display = "none";
}
else {
el.style.display = "block";
}
}
</script>
var getElementsByClassName = function(node, classname) {
if (document.getElementsByClassName) {
return document.getElementsByClassName(classname);
}
var a = [];
var re = new RegExp('(^| )'+classname+'( |$)');
var els = node.getElementsByTagName("*");
for(var i=0,j=els.length; i<j; i++)
if(re.test(els[i].className))a.push(els[i]);
return a;
}
var Toggle = function(){
var tp = getElementsByClassName(document.documentElement,'toggle');
for(var i = 0; i < tp.length; i++){
if(tp[i].style.display=='none')
tp[i].style.display='block'
else
tp[i].style.display='none'
}
}
Use getElementsByClassName and then loop through them.
EDIT
Just make sure they have the class toggle as used in my code above.
UPDATE
Added function for IE support (adopted from https://stackoverflow.com/a/7410966/600101).

Hiding all elements with the same class name?

I'm trying to hide elements with the same class name (float_form), but I'm also trying to use the script below to show them (all of the float_form class divs are initially hidden). I've looked at a lot of jquery solutions, but I can't seem to make any of them work for this.
function show(a) {
var e = document.getElementById(a);
if (!e)
return true;
if (e.style.display == "none") {
e.style.display = "block"
} else {
e.style.display = "none"
}
return true;
}
​
Edit: Sorry if it wasn't clear, I do not intend to use Jquery(and I know that this is not jquery). I am looking for a way to use javascript to recognize repeated classnames that are not in style= display:none; without compromising the show/hide ID element since there is a loop with the div id as the key. The html for the div looks like below, with {item.ID} being a while loop.
<div class="float_form" id="{item.ID}" style="display: none;">
vanilla javascript
function toggle(className, displayState){
var elements = document.getElementsByClassName(className)
for (var i = 0; i < elements.length; i++){
elements[i].style.display = displayState;
}
}
toggle('float_form', 'block'); // Shows
toggle('float_form', 'none'); // hides
jQuery:
$('.float_form').show(); // Shows
$('.float_form').hide(); // hides
If you're looking into jQuery, then it's good to know that you can use a class selector inside the parameters of $ and call the method .hide().
$('.myClass').hide(); // all elements with the class myClass will hide.
But if it's a toggle you're looking for, use .toggle();
But here's my take on a good toggle without using jQuery:
function toggle( selector ) {
var nodes = document.querySelectorAll( selector ),
node,
styleProperty = function(a, b) {
return window.getComputedStyle ? window.getComputedStyle(a).getPropertyValue(b) : a.currentStyle[b];
};
[].forEach.call(nodes, function( a, b ) {
node = a;
node.style.display = styleProperty(node, 'display') === 'block' ? 'none' : 'block';
});
}
toggle( '.myClass' );
Demo here (Click "Render" to run): http://jsbin.com/ofusad/2/edit#javascript,html
Using jquery
$(".float_form").each(function(){
if($(this).css("display") == "none"){
$(this).show();
}else{
$(this).hide();
}
});
No jQuery needed
const toggleNone = className => {
let elements = document.getElementsByClassName(className)
for (let i = 0; i < elements.length; i++){
if (elements[i].style.display === "none") {
elements[i].style.display = "";
} else {
elements[i].style.display = "none";
}
}
}
const toggleVisibility = className => {
let elements = document.getElementsByClassName(className)
for (let i = 0; i < elements.length; i++){
let elements = document.getElementsByClassName(className);
if (elements[i].style.visibility === "hidden") {
elements[i].style.visibility = "";
} else {
elements[i].style.visibility = "hidden";
}
}
}
// run
toggleNone('your-class-name-here'); // toggles remove
// or run
toggleVisibility('your-class-name-here'); // toggles hide
Answer provided in ES6 syntax but easily can be converted to ES5 if you wish
Try :
function showClass(a){
var e = [];
var e = getElementsByClassName(a);
for(i in e ){
if(!e[i])return true;
if(e[i].style.display=="none"){
e[i].style.display="block"
} else {
e[i].style.display="none"
}
}
return true;
}
demo : showClass("float_form");

How do I get all elements of a particular HTML tag in javascript?

I need to hide all elements of type 'section' in my document apart from one with a particular ID.
In jquery this would be easy
$("section").hide();
$("section#myId").show();
How would I do this without jquery??
(I need it to happen as soon as the page loads and to not be noticable). I also need it to work cross browser.
Thanks.
DOMElement.getElementsByTagName is your friend:
var sections = document.getElementsByTagName('section');
var mySection = null;
for(var i = 0; i < sections.length; ++i) {
if(sections[i].id === "myId") {
mySection = sections[i];
mySection.style.display = "block";
break;
}
sections[i].style.display = "none";
}
Place the following immediately before the </body> in your HTML
<script>
(function () {
for(var els = document.getElementsByTagName ('section'), i = els.length; i--;)
els[i].id !== "myId" && (els[i].style.display = "none");
}) ();
</script>
or in "modern" (HTML5) browsers :
<script>
[].forEach.call (document.querySelectorAll ('section'),
function (el) { el.id !== "myId" && (el.style.display = "none"); })
</script>

javascript hiding divs

I want to be able to have a javascript function that hides divs for me. For example, I have something like
<div id='container'>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
</div>
And i would like the function to hide every 'item' class element after say the first 3. How would i go about this?
Thanks for any help
In JS, you could do something like this, provided the item divs are the only children of the container div:
var itemDivs = document.getElementById("container").children;
for(var i = 0; i < itemDivs.length; i++) {
if(i > 2) {
itemDivs[i].style.display = 'none';
}
}
Try it here: http://jsfiddle.net/eY9ZD/
Otherwise, you could do this:
var divs = document.getElementById("container").getElementsByTagName("div");
for(var i = 0; i < itemDivs.length; i++) {
if(i > 2 && divs[i].className == 'item') {
itemDivs[i].style.display = 'none';
}
}
Try it here: http://jsfiddle.net/6TcWE/
And finally, if jQuery is an option, there's a one-liner using the gt selector:
$("#container div.item:gt(2)").hide();
Try it here: http://jsfiddle.net/J8wK6/
With plain JavaScript something like:
function hideElements(elements, start) {
for(var i = 0, length = elements.length; i < length;i++) {
if(i >= start) {
elements[i].style.display = "none";
}
}
}
Then you can do:
var elements = document.getElementById('container').getElementsByClassName('item');
hideElements(elements , 3);
Reference: getElementById, getElementsByClassName
Update:
Interestingly, IE8 seems to support the more powerful querySelectorAll() function. So if you don't care about < IE8, then you can also do:
var elements = document.querySelectorAll('#container .item');
hideElements(elements , 3);
Unfortunately, there is not the "one" solution to select the elements you want in all browsers. If you don't want to think about cross-browser compatibility, consider to use jQuery as #karim suggests.
You can do this easily with jQuery, but your tag doesn't include that so I'm going to show you a vanilla Javascript way:
var divs = document.getElementById('container').getElementsByTagName('div');
var numItemDivs = 0;
for (var i=0; i<divs.length; i++) {
if (divs[i].className == "item") {
numItemDivs++;
if (numItemDivs > 2) {
divs[i].style.display = "none";
}
}
}
If you are just using regular javascript you can do something like this:
var container = document.getElementById("container");
var items = container.childNodes;
for(var i = 0; i < items.length; i++){
if(i >= 3)
items[i].style.display = "none";
}
If you're looking for a pure javascript implementation, this should work; it will also only hide DIV child nodes.
function hideMe(){
var item_list = document.getElementById('container').children;
for(var i = 0; i < item_list.length; i++){
if(i > 2 && item_list[i].tagName == "DIV"){
item_list[i].style.display = "none";
}
}
}
EDIT: changed the style from visibility to display, you probably don't want the layout space lingering.

Categories