Wondering if someone can explain what this code means. What do the different lines mean and do?
function overlay(theTitle) {
el = document.getElementById("overlay");
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
el.innerHTML = theTitle;
}
function vindu(){
el=document.getElementById("vindu");
el.style.visibility=(el.style.visibility=="visible")?"hidden":"visible";
}
The only piece of this code that shouldn't be fairly self-explanatory is called the conditional operator (also called ternary).
For an example of how this works, val = test ? 'foo' : 'bar' is equivalent to the following:
if (test) {
val = 'foo';
} else {
val = 'bar';
}
el = document.getElementById("overlay");
searches an element in your html markup with the ID=overlay
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
sets the visibility style of the object to visible if it was hidden before and vice versa.
el.innerHTML = theTitle;
sets the innerHTML property to the variable which got passed in to the function. innerHTML is actually the content of the element and will show as text in your site
the other method does exactly the same for the element ID = vindu
Related
I need to find a very performant way to find out if a custom element or any of its parent elements has display: none;
First approach:
checkVisible() {
let parentNodes = [];
let el = this;
while (!!(el = el.parentNode)) {
parentNodes.push(el);
}
return [this, ...parentNodes].some(el => getComputedStyle(el).display === 'none')
}
Is there anything that runs faster than this? Is this even a safe method?
The reason I need this: We have a <data-table> custom element (native webcomponent) which does very heavy lifting in its connectedCallback(). We have an application that has like 20-30 of those custom elements in a single page, which leads to IE 11 taking like 15 seconds until the page is rendered.
I need to delay initialisation of those <data-table> components which are initially not even visible, so I need a way to test inside the connectedCallback() if the element is visible (which it is not if it is in one of the 18 tabs initially not shown).
The easiest way to see if an element or its parent has display:none is to use el.offsetParent.
const p1 = document.getElementById('parent1');
const p2 = document.getElementById('parent2');
const c1 = document.getElementById('child1');
const c2 = document.getElementById('child2');
const btn = document.getElementById('btn');
const output = document.getElementById('output');
function renderVisibility() {
const p1state = isElementVisible(p1) ? 'is visible' : 'is not visible';
const p2state = isElementVisible(p2) ? 'is visible' : 'is not visible';
const c1state = isElementVisible(c1) ? 'is visible' : 'is not visible';
const c2state = isElementVisible(c2) ? 'is visible' : 'is not visible';
output.innerHTML = `Parent 1 ${p1state}<br>Parent 2 ${p2state}<br/>Child 1 ${c1state}<br/>Child 2 ${c2state}`;
}
function isElementVisible(el) {
return !!el.offsetParent;
}
function toggle() {
p1.style.display = (p1.style.display ? '' : 'none');
p2.style.display = (p2.style.display ? '' : 'none');
renderVisibility();
}
btn.addEventListener('click', toggle),
renderVisibility();
<div id="parent1" style="display:none">
<div id="child1">child 1</div>
</div>
<div id="parent2">
<div id="child2">second child</div>
</div>
<button id="btn">Toggle</button>
<hr>
<div id="output"></div>
This code converts el.offsetParent into a boolean that indicates if the element is showing or not.
This only works for display:none
Not sure about performance, but it should be faster than your approach at least:
HTMLElement.prototype.isInvisible = function() {
if (this.style.display == 'none') return true;
if (getComputedStyle(this).display === 'none') return true;
if (this.parentNode.isInvisible) return this.parentNode.isInvisible();
return false;
};
For a pure function that:
returns TRUE if and only if neither the element itself nor any of its parents up to the document itself have style display === 'none'
returns FALSE if and only if either the element itself or any parent element up to the document itself have style display === 'none'
You can define the below function and then call it on the element you wish to validate:
function isVisible(element) {
// Start with the element itself and move up the DOM tree
for (let el = element; el && el !== document; el = el.parentNode) {
// If current element has display property 'none', return false
if (getComputedStyle(el).display === "none") {
return false;
}
}
// Neither element itself nor any parents have display 'none', so return true
return true;
}
I can't find a reason why the following code is not working:
var nav = document.getElementById("nav").style.visibility;
if (nav === "" || nav === "hidden")
nav = "visible";
else
nav = "hidden";
Can someone explain me why I cannot change nav in the if..else?
Because you're only assigning a value to a variable rather than updating that element.
var nav = document.getElementById("nav");
var visibility = nav.style.visibility;
if (visibility === "" || visibility === "hidden")
nav.style.visibility = "visible";
else
nav.style.visibility = "hidden";
Consider this
if (visibility === "" || visibility === "hidden")
document.getElementById("nav").style.visibility = "visible";
else
document.getElementById("nav").style.visibility = "hidden";
First layout the logic in code, the way you want it to work. Seems really clear what this code is about. At least it should to yourself! Once that is done, you can factor out the things your code might need later in the program. For example, if you will change the visibility of the element some more, then you will need to extract it to the outer scope.
var element_style = document.getElementById("nav").style;
if (visibility === "" || visibility === "hidden")
element_style.visibility = "visible";
else
element_style.visibility = "hidden";
In there, you had to leave out the .visibility from the element_style because then (in your if block) you are accessing the property of the object via . operator and assignment = and assigned it to string value. Meaning that your nav is assigned to a new string with a value of "visible or hidden", and you totally detached the object you wanted to change (that nav element).
In your code, you can log the nav to see what are you getting to confirm.
i don't really know any javascript but I've been able to piece together a means to programmatically hide html tables on a webpage using versions of the following line to hide them when the page opens:
document.getElementById("approved").style.display = "none";
etc
and then depending on a value being chosen from a select menu have the element appear, using this:
document.getElementById('cboaim').addEventListener('change', function (){
var style = this.value == "10" ? 'block' : 'none';
document.getElementById('approved').style.display = style;
var style = this.value == "13" ? 'block' : 'none';
document.getElementById('enddate').style.display = style;
var style = this.value == "14" ? 'block' : 'none';
document.getElementById('tortm').style.display = style;
var style = this.value == "17" ? 'block' : 'none';
document.getElementById('enddate').style.display = style;
});
Which works for virtually everything except for the two lines relating to 'enddate'. It works for ONE of the values but not the other. I'm assuming referring to the element id twice breaks this code (both select 13 and 17 need this date box to appear).
For more complex reasons I can't just add another table with a different id so I'm hoping somebody out there knows an easy way around the problem. Please be gentle with me, I know the javascript is probably offensive to a programmer ;-)
I'd also happily use a function attached to an onchange on the select if that was easier? I'm only using the addeventlistener because a search on stackoverflow came up with that particular solution.
Cheers
Les
Remove all those var statements. Declaring the same var in the same scope multiple times is invalid JS.
Now, the check for value "17" will always override that for "13", change the condition on the 'enddate' element:
document.getElementById('cboaim').addEventListener('change', function (){
document.getElementById('approved').style.display =
this.value == "10" ? 'block' : 'none';
document.getElementById('tortm').style.display =
this.value == "14" ? 'block' : 'none';
document.getElementById('enddate').style.display =
(this.value == "13" || this.value == "17") ? 'block' : 'none';
});
This will set 'enddate' to display if the value is "13" or if the value is "17".
You cannot have two elements with the same id because an id is meant to be an unique identifier. You must find a way to give the tables separate ids.
If you wanted to do something like this you could give them the same name (or class) instead and do something like this:
var style = this.value == "13" ? 'block' : 'none';
document.getElementsByName('enddate')[0].style.display = style; //First enddate element
style = this.value == "17" ? 'block' : 'none';
document.getElementsByName('enddate')[1].style.display = style; //Second enddate element
Also, every time you write var style = ... you are defining a new variable. Similar thing to above, variables should not really have the same name. So you should give them different names or remove the var keyword from all but the first one.
EDIT:
I have just realised that the question is not as clear as I thought: You might mean that if 13 or 17 are selected from the menu, the style is not always applied to the single element?
In this case, you need an if statement to decide if 13 OR 17 were selected, and apply the correct style. For example:
if((this.value == "17")||(this.value == "13")) {
document.getElementById('enddate').style.display = "block";
} else {
document.getElementById('enddate').style.display = "none";
}
The problem with your code is that the check for 17 was done separately and after the check for 13, overwriting that style. Therefore nothing happened when 13 was selected.
I'm making a tree structure using html and css.
This is the final structure that I should reach: http://jsfiddle.net/yrE7N/1/
What I need is, on clicking a node, its children node will appear.
I've done this till now:
JS Fiddle: http://jsfiddle.net/ZTkLg/11/
I've used this JS function
var _hidediv = null;
function showdiv(id) {
if(_hidediv)
_hidediv();
var div = document.getElementById(id);
div.style.display = 'block';
_hidediv = function () { div.style.display = 'none'; };
}
The thing is, the JS function doesn't seem to be toggling the visibility of the div stage-two.
I've used this function before on this page: http://leonardorestaurant.in/menu and it worked but I can't figure the problem out in this case.
Try
Some text here
and
var flag = true;
function showdiv(id) {
var div = document.getElementById(id);
div.style.display = flag ? 'none' : 'block';
flag = !flag;
}
Demo: Fiddle
The console in my browser prints out :
Uncaught TypeError: Cannot read property 'style' of null
Which means that here :
div.style.display = 'block';
div is not the result you think it should be... That tells us that id is not what we think here :
var div = document.getElementById(id);
Which I confirmed by using :
console.log(id);
inside your function.
The id value is actually the <div id="two">
So, basically you already have the element you're looking for.
However, you've got bigger problems, which is that you need a toggle function, I'm just guessing. Try using this :
function toggleDiv(id) {
var el = document.getElementById(id);
var newDisplayValue = "none";
if ( el.style.display && el.style.display === "none" ) {
newDisplayValue = "block";
}
el.style.display = newDisplayValue;
}
and change to this :
<a href=# onclick="toggleDiv('two');">
see it here
No idea where the problem lies, tried various things and I'm not having any luck. I've done this successfully before in the past but now it won't work, any help would be great...
HTML snippet:
<tr>
<td class="tableContent noBorderSides paddingAll"><img class="imgResize" src="images/emptyCircle.png" onclick="expandItem()"/>
<div id="Expand" class="hiddenDiv">
HELLO?
</div>
JavaScript:
function expandItem() {
if (document.getElementById("Expand").style.display == 'block') {
document.getElementById("Expand").style.display = 'none';
}
else if (document.getElementById("Expand").style.display == 'none') {
document.getElementById("Expand").style.display = 'block';
}
}
CSS:
.hiddenDiv {
display: none;
}
What am I doing wrong?
The initial display that is set in your CSS won't be reachable from the .style property.
Do it like this:
function expandItem() {
var expand = document.getElementById("Expand");
if (expand.style.display == '') {
expand.style.display = 'block';
}
else if (expand.style.display == 'block') {
expand.style.display = '';
}
}
Or a little shorter like this:
function expandItem() {
var expand = document.getElementById("Expand");
expand.style.display = (expand.style.display == '') ? 'none' : '';
}
Use .getComputedStyle() to get any style attributes associated with a given element. Notice, that the object returned is read only, so you'll want to use this for the initial if statement, and then set the style as you were doing above.
You could just remove the class from the element that defines the hidden property and add when you want to hide:
if (document.getElementById("Expand").className == '') {
document.getElementById("Expand").className = 'hiddenDiv';
}
else if (document.getElementById("Expand").className == 'hiddenDiv') {
document.getElementById("Expand").className = '';
}
Do note that if you have other classes on that element you will need to do a little string manip rather than just a straight check and remove.
//Temporary solution
//Replace your javascript code with following code
if (document.getElementById("Expand").style.display == 'block') {
document.getElementById("Expand").style.display = 'none';
}
else{
document.getElementById("Expand").style.display = 'block';
}
//Note :- Javascript detect '' (empty) when it try to search display property for expand block
#user1689607's answer is right if you need to just use javascript. If you have access to jQuery you can do it like so
$("#Expand").toggle();
And a simple jsfiddle to demonstrate: http://jsfiddle.net/P36YA/