I need a vanilla JS way to count the number of hidden divs on a page.
I have three divs with inline styles display: none. I thought this would work, but no luck:
var hiddenContainers = (document.getElementsByClassName(".emp-container").style.display == "none").length;
I have tried several solutions from SO and found a few JQuery ones that were successful, but what I'm writing needs to be done exclusively in regular old JavaScript.
EDIT: This works, but it seems like an unnecessarily roundabout way to get what I want:
var hiddenContainers = [];
var containers = document.querySelectorAll(".emp-container");
for (var i = 0; i < containers.length; i++) {
if (containers[i].style.display == "none") {
hiddenContainers.push(containers[i]);
}
}
function countclick(){
var m = document.querySelectorAll('.divs[style*="display:none;"]').length;
document.getElementById('count').innerHTML = "Hidden Divs: "+m;
}
<div class='divs' style="display:none;">a</div>
<div class='divs' style="">b</div>
<div class='divs' style="">c</div>
<div class='divs' style="display:none;">d</div>
<div class='divs' style="">e</div>
<div class='divs' style="display:none;">f</div>
<hr/>
<span id="count">Hidden Divs: 0</span><br/>
<button onclick='countclick();'>Count</button>
Related
I have a list of table columns. I would like to display them in one row.
What am I trying is :
for (var i = 0; i < key.length; i++) {
writeToScreen3('<div class="col-sm">' + key[i] + '</div>'); //column name
}
function writeToScreen3(message) {
var pre = document.createElement("p"); //I realize I am creating another element <p> How to do it diffrently?
pre.innerHTML = message;
output.appendChild(pre);
}
What I need is this transferred to JavaScript :
<div class="container">
<div class="row">
<div class="col-sm">
One of three columns
</div>
<div class="col-sm">
One of three columns
</div>
<div class="col-sm">
One of three columns
</div>
</div>
</div>
What I also tried :
function test8() {
$("#output").html('<div class="container">< div class= "row" >'); //but it always closes these 2 divs here . I want it not to close it. output is a div field
}
You can do something like this:
function createContainer(columns) {
function createDivWithClass(cls) {
const div = document.createElement('div');
div.classList.add(cls);
return div;
}
const container = createDivWithClass('container');
const row = createDivWithClass('row');
container.appendChild(row);
for (let i = 0; i < columns.length; i++) {
const column = createDivWithClass('col-sm');
column.textContent = columns[i];
row.appendChild(column);
}
return container;
}
const container = createContainer([1, 2, 3, 4]);
document.getElementById('output').appendChild(container);
console.log(container.outerHTML);
<div id="output"></div>
Here, I've defined a function called createDivWithClass to make it easier to create a <div> and set a class name to it.
Then, I'm using this function to create a <div class="container">, create a <div class="row"> and add that to the container, and then go through the columns array and create <div class="col-sm"> and add those to the row element.
Just like you can append elements to the #output element in the DOM, you can also append elements to elements that you've created and are not yet in the DOM.
I dynamically create a form. There is an add line button that adds a new line that includes a delete line button.
I originally wrote this in angular, and I was able to pass "$index" into the function to remove the specific line.
I am now rewriting my code in pure js, and my question is: How can I go about implementing this same functionality?
The example for deleting elements by index as per your requirement can be found in this jsfiddle : https://jsfiddle.net/ChaitanyaMunipalle/9z73rfjx/2/. I assume you will take care of adding lines & delete buttons dynamically. It contains only deletion.
As you have not given any code, I assumed the html would look like the below one:
<div id="lines">
<div class="line-item">
<input type="text" name="line-value"/> <button class="delete-line">Delete</button>
</div>
<div class="line-item">
<input type="text" name="line-value"/> <button class="delete-line">Delete</button>
</div>
<div class="line-item">
<input type="text" name="line-value"/> <button class="delete-line">Delete</button>
</div>
</div>
You have to add event listeners to delete buttons. And you have to use closure to save the index of the button clicked.
var deleteItem = function(index) {
var divElements = document.getElementsByClassName("line-item");
for (var i = 0; i < divElements.length; i++) {
if (i == index) {
divElements[i].parentNode.removeChild(divElements[i]);
break;
}
}
};
var deleteButtons = document.getElementsByClassName("delete-line");
for (var i = 0; i < deleteButtons.length; i++) {
(function(index){
deleteButtons[i].addEventListener('click', function() {
deleteItem(index);
}, false);
})(i);
}
I don't quite understand your setup, but removing a div is just
parentNode.removeChild(yourDiv)
If you only have the parentNode but know the index of the div you want to delete, then
parentNode.removeChild(parentNode.children[i])
`<div id="div1">
<p id="p1">This is a paragraph.</p>
<p id="p2">This is another paragraph.</p>
</div>
<script>
var parent = document.getElementById("div1");
var child = document.getElementById("p1");
parent.removeChild(child);
</script>`
This a example in jsfiddle:
https://jsfiddle.net/AlfonsoRamirez9/ttj1sLo5/
I hope help you :)
I need some help with the click event, I'm trying to have an individual counter that is incremented by the click event that I have on the img. I've tried many variations, I want to resolve this without using jQuery.
<script async>
var count = 0;
var clickerCount = document.getElementsByClassName('clicker');
var cat = {
count : 0,
counter: function(){
this.count++;
clickerCount.textContent = "Kitten Click Count :" + this.count;
console.log("counter function working");
console.log(cat.count);
}
};
function modifyNum(){
cat.counter();
console.log("modifyNum function working");
}
</script>
</head>
<body>
<div style="display:inline">
<div>
<img src="http://placekitten.com/200/296" id="cat0" onclick="modifyNum();">
<p id='clicker'>Kitten Click Count :</p>
</div>
<div>
<img src="http://placekitten.com/200/296" id='cat1' onclick="modifyNum();">
<p id='clicker'>Kitten Click Count :</p>
</div>
</div>
For a start, you are using id='clicker' in two places (IDs are supposed to be unique), and then using document.getElementsByClassName, which returns nothing because you used an ID and not a class.
Once you do change it to a class, document.getElementsByClassName will return an array of elements. You'll have to use clickerCount[0] and so on, or loop through the array.
This example should work. I've separated the HTML from the Javascript because it looks clearer for me. You can use it as an example to expand / create your own in your own way.
Hope it help
HTML:
<div style="display:inline">
<div>
<img src="http://placekitten.com/200/296" id="1" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-1">0</span>
</div>
<div>
<img src="http://placekitten.com/200/296" id="2" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-2">0</span>
</div>
</div>
JS:
var imagesCountable = document.getElementsByClassName("countable");
var counters = [];
for (var i = 0; i < imagesCountable.length; i++) {
counters[imagesCountable[i].id] = 0;
imagesCountable[i].onclick = function(e) {
document.getElementById("counter-for-" + e.currentTarget.id)
.innerHTML = ++counters[e.currentTarget.id];
}
}
var imagesCountable = document.getElementsByClassName("countable");
var counters = [];
for (var i = 0; i < imagesCountable.length; i++) {
counters[imagesCountable[i].id] = 0;
imagesCountable[i].onclick = function(e) {
var cElem = document.getElementById("counter-for-" + e.currentTarget.id);
cElem.innerHTML = ++counters[e.currentTarget.id];
}
}
<div style="display:inline">
<div>
<img src="http://placekitten.com/200/296" id="1" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-1">0</span>
</div>
<div>
<img src="http://placekitten.com/200/296" id="2" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-2">0</span>
</div>
</div>
I have solved this problem in this JSFiddle!
If you can hardcode the IDs then it's easier in my point o view to just manipulate things by ID.
<div>
<img src="http://placekitten.com/200/296" id="cat0" onclick="counter(0);">
<p id='clicker0'>Kitten Click Count :</p>
<input type="hidden" id="counter0" value="0">
</div>
function counter(id) {
var cnt = parseInt(document.getElementById("counter" + id).value);
cnt++;
document.getElementById("counter" + id).value = cnt;
document.getElementById('clicker' + id).innerHTML = 'Kitten Click Count :' + cnt;
}
It's not the same approach but I find it easy to understand.
Hope it helps.
Ok, so first off you have two elements with the id of 'clicker'. You probably meant for those to be classes and ids. So when you call modifynum() it cant locate those because the class doesn't exists. Second, your JS is loading before your HTML elements. So when the JS gets to this line:
var clickerCount = document.getElementsByClassName('clicker');
It is going to find nothing, even if you correct the class names. So you want to move your JS to the footer of your HTML document, or wrap the code in a method that is called on pageLoad().
I think that should take care of it. Your object, for the most part, looks correct.
I want to fill differents divs with four colours, using only javascript (with a HTML structure off course), here's the code :
HTML
<div id="content">
<div id="carre1" class="carre">1</div>
<div id="carre2" class="carre">2</div>
<div id="carre3" class="carre">3</div>
<div id="carre4" class="carre">4</div>
</div>
JS
var colors = {
count: 4,
tab : ["red","orange","yellow","green"]}
;
Let's say I want to make the div "carre1" red, how do I do that ?
Thanks in advance !
for (var i = 0; i < colors.tab.length; i++) {
document.getElementById("carre" + (i + 1)).style.backgroundColor= colors.tab[i];
In short:
for (var i=1; i<=colors['count']; i++) {
document.getElementById("carre" + i).style.backgroundColor = colors['tab'][i-1];
}
See this jsfiddle.
Also works with colors.tab and colors.count as in this jsfiddle.
This is how you fill div's with colors in order they are stored in array:
carre = document.getElementsByClassName('carre');
for(i=0;i<colors.count;i++){
carre[i].style.backgroundColor = colors.tab[i];
}
document.getElementById("carre1").style.backgroundColor=colors.tab[0];
I have some tables here, and using this javascript below, I made them hide and show every time a user click on their buttons. What I want to add in to this script, is when someone click on a table's button to show-up, all the other to be hidden. Any idea how can I do this? Thank you in advance!
This is my html code:
<table id="SC1_TH_" class="header_op"><tr><td>
<div id="SC1_BSH_" onClick="SC[1]();" class="hide_button">*</div>OPTION ONE
</td></tr></table>
<div id="SC1_BO_" style="display:dlock;">BLAH BLAH</div>
<table id="SC2_TH_" class="header_cl"><tr><td>
<div id="SC2_BSH_" onClick="SC[2]();" class="show_button">*</div>OPTION ONE
</td></tr></table>
<div id="SC2_BO_" style="display:none;">BLAH BLAH</div>
<table id="SC3_TH_" class="header_cl"><tr><td>
<div id="SC3_BSH_" onClick="SC[3]();" class="show_button">*</div>OPTION ONE
</td></tr></table>
<div id="SC3_BO_" style="display:none;">BLAH BLAH</div>
This is my javascript:
<script type="text/javascript">
var SC = [];
for (var i = 1; i < 10; i++) {
SC[i] = (function(i){
return function(){
var SC_TH = document.getElementById('SC'+i+'_TH_');
var SC_BSH = document.getElementById('SC'+i+'_BSH_');
var SC_BO = document.getElementById('SC'+i+'_BO_');
if (SC_BO.style.display == 'block' || SC_BO.style.display == ''){
SC_TH.className = 'header_cl';
SC_BSH.className = 'show_button';
SC_BO.style.display = 'none';}
else {SC_TH.className = 'header_op';
SC_BSH.className = 'hide_button';
SC_BO.style.display = 'block';}
}})(i);}
</script>
EDIT: In other words, I need something to say, if this button that clicking right now is something all the other to be hidden!!!
Here's a working example with some very simple jQuery (recommended) code.
HTML:
<table><tr><td>
<div class="toggle-button">*</div>OPTION ONE
</td></tr></table>
<div class="toggle">BLAH BLAH</div>
<table><tr><td>
<div class="toggle-button">*</div>OPTION ONE
</td></tr></table>
<div class="toggle">BLAH BLAH</div>
<table><tr><td>
<div class="toggle-button">*</div>OPTION ONE
</td></tr></table>
<div class="toggle">BLAH BLAH</div>
JS:
$(function() {
$('div.toggle').hide();
$('.toggle-button').click(function(){
$('div.toggle').hide();
$(this).closest('table').next('div.toggle').show();
});
});
As #StephenByrne mentioned, I also strongly recommend using an existing component such as jQuery Accordian. It takes minutes to implement and comes with a whole host of themes to chose from and is fully customisable. You could spend hours or days writing your own. Unless it's a learning exercise, it's simply a waste of time. No need to reinvent the wheel.
As you have indicated a strong push towards js-only, here's a working js-only solution.
HTML:
<table id="SC1_TH_" class="header_op"><tr><td>
<div id="SC1_BSH_" onclick="toggle(this);" class="hide_button">*</div>OPTION ONE
</td></tr></table>
<div id="SC1_BO_" style="display:block;">BLAH BLAH</div>
<table id="SC2_TH_" class="header_cl"><tr><td>
<div id="SC2_BSH_" onclick="toggle(this);" class="show_button">*</div>OPTION ONE
</td></tr></table>
<div id="SC2_BO_" style="display:none;">BLAH BLAH</div>
<table id="SC3_TH_" class="header_cl"><tr><td>
<div id="SC3_BSH_" onclick="toggle(this);" class="show_button">*</div>OPTION ONE
</td></tr></table>
<div id="SC3_BO_" style="display:none;">BLAH BLAH</div>
JS:
function toggle(src) {
var id = src.id;
var index = id.substring(2, 3);
var i = 1;
var toggleItem = document.getElementById('SC' + i.toString() + '_BO_');
while (toggleItem != null) {
var bShow = index == i;
var button = document.getElementById('SC' + i.toString() + '_BSH_');
var table = document.getElementById('SC' + i.toString() + '_TH_');
if (bShow) {
toggleItem.style.display = 'block';
toggleItem.className = 'setitemclassname';
button.className = 'setbuttonclassname';
table.className = 'settableclassname';
}
else {
toggleItem.style.display = 'none';
toggleItem.className = 'setitemclassname';
button.className = 'setbuttonclassname';
table.className = 'settableclassname';
}
toggleItem = document.getElementById('SC' + (++i).toString() + '_BO_');
}
}
Inside the while loop when index == i evaluates to true, you know you have the item to show. Add extra logic there to change your class names.
A cleaner solution involves altering your HTML a bit as well - getting rid of the onclick and replacing it with a class (toggleItem) that will allow the javascript to identify the items to be toggled. I also make sure that all the buttons have the class button so they can be identified.
<table id="SC1_TH_" class="header">
<tr>
<td>
<div id="SC1_BSH_" class="button">*</div>OPTION ONE</td>
</tr>
</table>
<div id="SC1_BO_" class="toggleItem">BLAH BLAH</div>
<table id="SC2_TH_" class="header">
<tr>
<td>
<div id="SC2_BSH_" class="button">*</div>OPTION ONE</td>
</tr>
</table>
<div id="SC2_BO_" class="toggleItem">BLAH BLAH</div>
<table id="SC3_TH_" class="header">
<tr>
<td>
<div id="SC3_BSH_" class="button">*</div>OPTION ONE</td>
</tr>
</table>
<div id="SC3_BO_" class="toggleItem">BLAH BLAH</div>
Then in the javascript:
var buttons = document.getElementsByClassName('button'),
toggleItems = document.getElementsByClassName('toggleItem'),
tables = document.getElementsByClassName('header');
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = getFunction(toggle, i);
}
// getFunction is needed for reasons to do with variable scope
function getFunction(f, p) {return function() {f(p)}}
function toggle(selected) {
for (var i = 0; i < toggleItems.length; i++) {
toggleItems[i].style.display = i == selected ? '' : 'none';
tables[i].className = i == selected ? 'header open' : 'header closed';
buttons[i].className = i == selected ? 'button show' : 'button hide';
}
}
toggle(0); // initially show only the first one
(This does assume that the buttons and toggle items will be in the same order. If that is not the case you will have to revert to checking their IDs or find some other way to associate the items and buttons.)
(EDITED to include changing class of tables and buttons)
Just hide all of them, then show the one that should become toggled open. This script is not the elegantest solution, but integrates directly in your coding style:
for (var i = 1; i < 10; i++) {
SC[i] = (function(i){
var SC_TH = document.getElementById('SC'+i+'_TH_'),
SC_BSH = document.getElementById('SC'+i+'_BSH_'),
SC_BO = document.getElementById('SC'+i+'_BO_');
return function(action) {
if (!action) action = SC_BO.style.display=="none" ? "show" : "hide";
if (action == "show") {
for (var i=0; i<SC.length; i++)
SC[i]("hide");
SC_TH.className = 'header_op';
SC_BSH.className = 'hide_button';
SC_BO.style.display = '';
} else {
SC_TH.className = 'header_cl';
SC_BSH.className = 'show_button';
SC_BO.style.display = 'none';
}
};
})(i);
}