style.display="none" works in else{} but not in if{} - javascript

JS:
function ToggleShow(lang_option){
var elements = document.getElementsByClassName(lang_option);
var langs = document.getElementsByClassName("lang");
for(var i=0,l=elements.length;i<l;i++){
if(elements[i] in langs){
elements[i].style.display="block";
}else{
elements[i].style.display="none";
}
}
}
HTML:
<button type="button" class="btn btn-primary" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="ToggleShow('lang-compiled')">
Compiled
</button>
<div class="lang lang-interpreted">Python 3</div>
<div class="lang lang-compiled">C</div>
works, but if I reverse the two display functions (change elements[i].style.display="block"; to elements[i].style.display="none"; and vice versa), the buttons stop functioning without any errors in console.

if(elements[i] in langs){ tests if the element in question is a property of the langs HTMLCollection, which is of course always false. If you wanted to check if the element is included in the HTMLCollection, you might turn the HTMLCollection into an array and use .includes:
function ToggleShow(lang_option) {
var elements = document.getElementsByClassName(lang_option);
var langs = [...document.getElementsByClassName("lang")];
for (var i = 0, l = elements.length; i < l; i++) {
if (langs.includes(elements[i])) {
elements[i].style.display = "block";
} else {
elements[i].style.display = "none";
}
}
}
Or, you might trim your function to something like this, to keep your code DRY:
function ToggleShow(lang_option) {
var langs = [...document.getElementsByClassName("lang")];
document.querySelectorAll('.' + lang_option).forEach(element => {
element.style.display = langs.includes(element)
? 'block'
: 'none';
});
}

we use in to check a property in an object, not a value. Just need to change the expression of if block to make the code work...
function ToggleShow(lang_option) {
var elements = document.getElementsByClassName(lang_option);
var langs = document.getElementsByClassName("lang");
for(var i=0,l=elements.length;i<l;i++) {
elements[i].style.display= langs.includes(elements[i]) ? "block" : "none";
}
}

Related

Can't get child element with DOM

My code looks like this:
function myFunction(result) {
var json = JSON.parse(result)
var jsonKeys = Object.keys(json)
var items = document.getElementById("items");
var adds = items.getElementById("add");
clearA()
var i;
for (i = 0; i < jsonKeys.length; i++) {
var btn = document.createElement("BUTTON");
console.log(jsonKeys[i]);
btn.innerHTML = jsonKeys[i]
btn.setAttribute("id", jsonKeys[i]);
btn.onclick = function() { run(this.id); }
items.appendChild(btn)
}
}
I can get items and use them but when I try to get the child element "add" I get items.getElementById is not a function
This is the html:
<div id="items">
<div id="add">
<input type="submit" value="add" onclick="foo(add)">
</div>
</div>
Change it to:
var items = document.getElementById("items");
var adds = document.getElementById("add");
Since ids are meant to be unique on a document, only document.getElementById exists. You could use items.querySelector('#id'), but this is probably a manifestation of a larger problem where you have similar HTML structure for multiple elements, with duplicated ids. In this case, it is recommended that you switch to classes and use items.querySelector('.classname').

How do I clear the innerHTML of a h1 tag

I'm just trying to make a simple mobile-based calculator. So far I've managed to display the digits pressed up to a certain character limit. I'm trying to make it so it clears the digits within the h1 tag that serves as the display.
I've tried using .innerHTML = "", but that isn't working. How should I fix this?
HTML
<body>
<h1 id="display">Calculator</h1>
<div class="buttons container" id="arithmetic">
<button onclick="clear()" onkeypress="clear()">AC</button>
<button><sup>+</sup>⁄<sub>−</sub></button>
<button>%</button>
<button>÷</button>
<button onclick="number(7)" onkeypress="number(7)">7</button>
<button onclick="number(8)" onkeypress="number(8)">8</button>
<button onclick="number(9)" onkeypress="number(9)">9</button>
<button>×</button>
<button onclick="number(4)" onkeypress="number(4)">4</button>
<button onclick="number(5)" onkeypress="number(5)">5</button>
<button onclick="number(6)" onkeypress="number(6)">6</button>
<button>−</button>
<button onclick="number(1)" onkeypress="number(1)">1</button>
<button onclick="number(2)" onkeypress="number(2)">2</button>
<button onclick="number(3)" onkeypress="number(3)">3</button>
<button>+</button>
<button>.</button>
<button id="doubleSpace" onclick="number(0)" onkeypress="number(0)">0</button>
<button>=</button>
</div>
<div class="calcOptions container">
<button>Arithmetic</button>
<button>Algebra</button>
<button>Calculus</button>
<button>Statistics</button>
</div>
</body>
JavaScript
var currentQuery;
var pastQuery;
var queryLength = document.getElementById("display").innerHTML.length;
function number(n) {
if (document.getElementById("display").innerHTML == "Calculator") {
document.getElementById("display").innerHTML = "";
}
if (queryLength >= 15) {
} else {
currentQuery = document.getElementById("display").innerHTML;
currentQuery += n;
document.getElementById("display").innerHTML = currentQuery;
}
}
function clear() {
currentQuery = "";
document.getElementById("display").innerHTML = currentQuery;
}
You can't name a javascript function with clear(), and the value of queryLength should set after the document ready replace your code by:
var currentQuery;
var pastQuery;
var queryLength;
document.addEventListener("DOMContentLoaded", function(event) {
var queryLength = document.getElementById("display").innerHTML.length;
})
function number(n) {
if (document.getElementById("display").innerHTML == "Calculator") {
document.getElementById("display").innerHTML = "";
}
if (queryLength >= 15) {
} else {
currentQuery = document.getElementById("display").innerHTML;
currentQuery += n;
document.getElementById("display").innerHTML = currentQuery;
}
}
function clearValue() {
currentQuery = "";
document.getElementById("display").innerHTML = currentQuery;
}
and the clear button with:
<button onclick="clearValue()" onkeypress="clearValue()">AC</button>
The problem is that the name of your function clear is already used by this native function document.clear(). Here is a deeper look on why this native function is called and not your function: Is “clear” a reserved word in Javascript?.
The solution is to simply rename your clear() function to something else e.g. allcancel()
You can try using .innerText = "".

How to Show Next/Previous item of an array?

I'm writing the first item of an array to the screen, and would like to create Next/Previous buttons for array, but I can't get it to work. I have tried several methods, but I can't find suitable solution.
Can anyone help?
This is the last one I have tried:
var data = [
{"subject":"starcraft2",
"date":"08.31",
"dDay":"mon",
"content1":"STARCRAFT2",
"content2":"season2",
"playerA":"Ju",
"playerB":"Lee",
"emblemA":"Terran",
"emblemB":"Zerg",
"result":"end"},
{"subject":"starcraft2",
"date":"08.29",
"dDay":"wed",
"content1":"STARCRAFT2",
"content2":"season2",
"playerA":"kim",
"playerB":"joo",
"emblemA":"Terran",
"emblemB":"Protoss",
"result":"end"},
];
function prevAction() {
// function (e) { // the e here is the event itself
alert("Prev Click!");
// document.getElementById('subject').textContent = prevItem();
// document.getElementById('date').textContent = prevItem();
for (var i = 0; i<data.length; i++)
for (var j=0; j<data[i]; j++)
while(j === 0)
{
j == j++;
console.log(j);
}
console.log(data[j].date + ', ');
document.getElementById('date').textContent = data[j].date;
// document.getElementById('subject').textContent = j[0];
}
Here's the jist of how you'd accomplish this in pure Javascript:
getNextItem() {
var index = document.getElementById("index").value;
//add guards here to prevent array overflow/underflow
if (data.length < index - 1) {
index.value++;
}
document.getElementById("DOM_ELEMENT_TO_ATTACH_DATA").innerHTML = data[index];
}
getPreviousItem() {
var index = document.getElementById("index").value;
//add guards here to prevent array overflow/underflow
if (index > 0) {
index.value--;
}
document.getElementById("DOM_ELEMENT_TO_ATTACH_DATA").innerHTML = data[index];
}
<input id="index" type="hidden" name="index" value="0">
<button type="button" onclick="getNextItem()">Next Item</button>
<button type="button" onclick="getPreviousItem()">Previous Item</button>
Note that this will just attach the pure json data to a DOM element, it won't do anything fancy with it.
Furthermore, if you want to do anything more complex, I'd strongly recommend you look into using a library like jQuery or Angular as it's going to make your life a whole lot easier in the long run.

Get a div inside a td with Javascript

I want to get the text inside the div in the class "atName".
I am looping though the table td's like this:
var searchString = document.getElementById("search").value;
if (searchString !== "") {
var cols = document.querySelectorAll('#theTable td'),
colslen = cols.length,
i = -1;
while (++i < colslen) {
if (cols[i].id.indexOf(searchString) > -1) {
cols[i].style.opacity = "1"
} else {
Here i want to access the text inside the div
}
Every td is set up like this:
<td id="H" class="element nonmetal gasI">
<div class="atN">1</div>
<div class="atS gas"><a class="gas" href="https://en.wikipedia.org/wiki/Hydrogen" target="_blank">H</a></div>
<div class="atName">Hydrogen</div>
<div class="atW">1.00794</div>
</td>
I want the text inside the "atName" div.
Does anyone know how?
Thanks!
The same way you selected the tds:
cols[i].querySelector('.atName').textContent;
btw. you should give different IDs to your tds or use classes because IDs should be unique
UPDATE
To avoid any confusion, I'm already assuming we're looping the tds (from your code), and this line goes here:
while (++i < colslen) {
if (cols[i].id.indexOf(searchString) > -1) {
cols[i].style.opacity = "1"
} else {
var divText = cols[i].querySelector('.atName').textContent; // <--- here
}
...
}
You can get the object by class name :
document.getElementsByClassName('atName')
But this return you a list of object with this class.
So you can do in your while:
while (++i < colslen)
{
if (cols[i].id.indexOf(searchString) > -1) {
cols[i].style.opacity = "1"
} else {
var text = cols[i].getElementsByClassName('atName')[0].textContent;
}
}
Maybe this will help?
var searchString = "Hy";
if (searchString !== "") {
var cols = document.querySelectorAll('#theTable tr td .atName');
for (var i=0;i<cols.length;i++)
{
if (cols[i].innerHTML.indexOf(searchString)>-1)
{
alert(cols[i].innerHTML);
}
}
}
What you're looking for is element.innerHTML but hopefully this selector trick will help you too.
Edit: element.textContent is different but you might desire to use it instead.

Storing variables in functions

Let's say you want to predefine a lot of buttons that are created by a button generator.
function createButton(name, func){
var btn = '<div class = "button" name = '+name+'/>';
$('.btn[name = "'+name+'"]').on('click', function(func){});
}
var butn1 = {
name : "exit",
func : func1
}
createButton(btn1);
Now if you had 100 buttons, this means a lot of variables. Is that bad? If it is, would this be better?
function chooseButton(name){
var btn;
switch(name){
case "exit":
btn = {
name : "exit",
func : func1
}
break;
case......
}
return btn;
}
var myBtn = chooseButton('exit');
createButton(myBtn);
If feel like it would be better to use a more general constructor for this sort of thing, assuming I've understood your question.
HTML
<div id="buttonContainer">
<button class="btn btn-type-a">Type A Button</button>
<button class="btn btn-type-b">Type B Button</button>
<!-- add further types -->
</div>
JS
var _functs = {
typeA: function () { alert('type A funct'); },
typeB: function () { alert('type B funct'); }
};
var _buttons = document.getElementById('buttonContainer')[0].childNodes;
for (var _i = 0; _i < _buttons.length; _i++) {
if (_buttons[_i].classList.contains('btn-type-a')) {
/*
node.classList.contains (not supported by IE < 10)
$(_buttons[_i]).hasClass('btn-type-a') if you're using jQuery
*/
_buttons[_i].addEventListener('click', _functs.typeA, false);
}
// other logic for other button assignment
};

Categories

Resources