onclick has to be clicked twice to fire - javascript

My onclick function won't fire unless it is clicked twice. I am very new to javascript but so far i trie moving around the var obj line, and changing the =="none" to "none"?"empty"; which are both things I didn't understand but saw other people did to fix this problem. Neither worked.
+
function showDiv(id){
var obj = document.getElementById(id);
if( obj.style.display == "none") {
obj.style.display='block'
}
else{
obj.style.display='none'
}
}
<div id="show1">
Roughly 2-3 months.
</div>

Your problem is, that you use the style property of the element directly. Assuming, that you did not set obj.style.display = "none"; in your code explicitly, the value remains undefined until the first click. After the first click it is set and everything works like you want it to.
To solve it use getComputedStyle() to access the element's style. This includes all styles set via CSS:
function showDiv(id){
var obj = document.getElementById(id),
compStyle = window.getComputedStyle( obj );
if( compStyle.display == "none") {
obj.style.display='block'
} else {
obj.style.display='none'
}
}

You should use strict equal operators to prevent from undefined style rule.
I would rather use addEventListener instead of onclick to keep my code cleaner, here is a jsfiddle with my version (some extras as dataset and triple conditional are there, but they are not necessarily needed in your example)
var showDiv = function (ev) {
var id = ev.currentTarget.dataset.id;
var obj = document.getElementById('show' + id);
obj.style.display = (obj.style.display === "none") ? 'block' : 'none';
};
http://jsfiddle.net/mindcookin/06nvkay7/4/

Related

Toggle Style Javascript

I am trying to write a simple toggle function in Javascript. What it does is take an element, a style name, and a desired value. If the current value of that style on the element is the empty string, that means it hasn't been set, so we set it to the given value. Otherwise, set it to the empty string to disable it.
My code is below:
function toggleStyle(el, styleName, value) {
if (el.styleName === '')
{
el.styleName = value;
}
else
{
el.styleName = '';
}
}
However, I'm unsure how I call this function if I want to toggle the visbility of a box. I know to directly change the visibility: I would normally do:
var box = document.getElementById("box");
box.style.display = "none";
But how would I call my toggleStyle to do this? I've tried writing:
toggleStyle (box, display, "none");
toggleStyle (box, style.display, "none");
toggleStyle (box.style, display, "none");
but nothing seems to work.
bracket notation is what you need and you need to pass strings.
function toggleStyle(el, styleName, value) {
if (el.style[styleName] !== value) { //better to check that it is not the value you have
el.style[styleName] = value;
} else {
el.style[styleName] = '';
}
}
var btn = document.querySelector("button")
var div = document.querySelector("#foo")
btn.addEventListener("click", function () {
toggleStyle(div, "display", "none")
});
<button type="button">Click Me</button>
<div id="foo">FOO</div>
Where would this fail? Color codes are one thing, but this is the basic step in the right direction.
You should write it like this instead:
function toggleProp(obj, prop, value){
obj[prop] = obj[prop] ? "" : value;
}
toggleProp(box.style, "display", "none");
You should also learn how to use the debugger:
From this we can see that it was because the variable display is not defined before using it.
Two things:
First, change your toggleStyle function so that it modifies the element's style property directly, and use bracket notation to dynamically access the property element of the style object:
function toggleStyle(el, styleName, value) {
if (el.style[styleName] === '') {
el.style[styleName] = value;
} else {
el.style[styleName] = '';
}
}
Second, pass a string of the style property when you use toggleStyle:
toggleStyle(box, "display", "none"); // display needs to be in quotes

CSS style not reverting using JavaScript

I am trying to set a CSS property back and forth using JavaScript depending on its value.
The class name menu is set to be hidden on page load. When I call the function to set it to visible it is successful. However, when I call it again to change it back it doesn't set it to hidden. It is seen as always set to visible.
let menu = document.querySelector('.menu');
if (menu.style.visibility = 'hidden') {
menu.style.visibility = 'visible';
console.log('visible'); // always shows this.
} else {
menu.style.visibility = 'hidden';
console.log('hidden'); // doesn't get to here when .menu is visible.
}
I am confused as to why it can do the first but not the second. I have tried using a else if condition:
else if (menu.style.visibility = 'visible')
I also tried using the setAttribute method but it's always the same outcome.
I need to be able to switch back and forth.
In JavaScript by using = you assign a value to something BUT if you use == you are checking if something is equal to something else.
let menu = document.querySelector('.menu');
if (menu.style.visibility == 'hidden') {
menu.style.visibility = 'visible';
console.log('visible'); // always shows this.
} else {
menu.style.visibility = 'hidden';
console.log('hidden'); // doesn't get to here when .menu is visible.
}
Kindly use below condition
if (menu.style.visibility == 'hidden') //change ==
Your conditional isn't valid. You're actually setting the value in the if statement.
if (menu.style.visibility = 'hidden') // this sets the value
It should be this:
if (menu.style.visibility == 'hidden') // this compares the value
This code will toggle the visibility of a div on your page.
function togglediv() {
var div = document.getElementById("menu");
div.style.display = div.style.display == "none" ? "block" : "none";
}
<button onclick="togglediv('menu')">Toggle div</button>
<div id="menu">div</div>
The error is in your if statement. So if you change the single equality to a double equal sign: ==, your code should work:
like:
if (menu.style.visibility == 'hidden')
Your syntax for comparing is wrong you need to use == while comparing any field in javascript so just do :
if (menu.style.visibility == 'hidden') {
menu.style.visibility = 'visible';
console.log('visible'); // always shows this.
} else {
menu.style.visibility == 'hidden';
console.log('hidden'); // doesn't get to here when .menu is visible.
}

How to hide then restore to initial state (= not always "block")?

Here's the JavaScript code you can find everywhere when you want to hide/show an element:
function sh(_id, _val) {
if (document.getElementById) {
document.getElementById(_id).style.display = _val;
}
else {
if (document.layers) {
document._id.display = _val;
}
else {
document.all._id.style.display = _val;
}
}
}
function hide(_id) {
sh(_id, 'none');
}
function show(_id) {
sh(_id, 'block');
}
The problem is the "show" function: it forces to "block". If I use a table with tr's and td's, when I want to display them I don't them to be displayed as "block" but to restore to their initial state.
How should I do?
How would you do?
If you want to restore their default display value, you can assign an empty string to it:
element.style.display = '';
If you want the one assigned through CSS for example, you have to store it somewhere, e.g. in an id -> display map or as data- attribute.
The easiest way would be to use jQuery and .show() http://api.jquery.com/show/
The second easiest way would be to wrap the table in a div.
If not I would try to store the initial value of display somewhere (if html5 the a "data-" attribute) if not in some other hidden element
If the point of your exercise is to learn more about DOM, then you may disregard this answer. But if the point is to get some UI to work, then:
My suggestion would be to use jquery. If you did, all of the code you showed would disappear altogether, and you would hide/show elements like this:
$('#' + id).hide()
$('#' + id).show()
If you want to stick with low level DOM api, then you'll have to save away the prior value (block or whatever) of style.display, so you can restore it later. And you can do that. But you'll keep having to write code like that, considering all kinds of cases, when someone has already written code that does that, and they're giving it away for free.
var previousDisplay = {};
function sh(_id, _val) {
if (document.getElementById) {
document.getElementById(_id).style.display = _val;
}
else {
if (document.layers) {
if(!previousDisplay[_id]){
previousDisplay[_id] = document._id.display;
}
document._id.display = _val;
}
else {
if(!previousDisplay[_id]){
previousDisplay[_id] = document.all._id.style.display;
}
document.all._id.style.display = _val;
}
}
}
function hide(_id) {
sh(_id, 'none');
}
function show(_id) {
var style = previousDisplay[_id];
if(!style){
style = 'block';
}
sh(_id, style );
}

Javascript toggle issue

This is my script :
window.onload = function (){
var title = document.getElementsByTagName('h1')[0].id = "heading1";
document.getElementById(title).onclick = function (e){
var para = this.nextSibling.style.display = 'block';
var newVal = (para == "block") ? "none" : "block";
alert(newVal);
}
}
The result I need is for the alert value to toggle from block to none and back. But I am always getting "none". What is the problem with my code?
window.onload = function () {
var firstH1 = document.getElementsByTagName('h1')[0];
firstH1.id = "heading1";
firstH1.onclick = function() {
var currentValue = this.nextSibling.style.display;
this.nextSibling.style.display = (currentValue == "none") ? "block" : "none";
}
}
Note a few things: I simplified your element fetching because it doesn't make sense to fetch an element, assign it an id, then use that id to find that same element again.
I also switched block/none ordering, because if no style is displayed then it would be blank -- and your first click would assign block to it - and it would not disappear. This way it does.
Well, para will always be "block", and therefore newVal will always be "none". So that behavior is expected. What are you trying to do? you are not toggling the property with your curent code.

Performance issues in javascript onclick handler

I have written a game in java script and while it works, it is slow responding to multiple clicks. Below is a very simplified version of the code that I am using to handle clicks and it is still fails to respond to a second click of 2 if you don't wait long enough. Is this something that I need to just accept or is there a faster way to be ready for the next click?
BTW, I attach this function using AddEvent from the quirksmode recoding contest.
var selected = false;
var z = null;
function handleClicks(evt) {
evt = (evt)?evt:((window.event)?window.event:null);
if (selected) {
z.innerHTML = '<div class="rowbox a">a</div>';
selected = false;
} else {
z.innerHTML = '<div class="rowbox selecteda">a</div>';
selected = true;
}
}
The live code may be seen at http://www.omega-link.com/index.php?content=testgame
You could try to only change the classname instead of removing/adding a div to the DOM (which is what the innerHTML property does).
Something like:
var selected = false;
var z = null;
function handleClicks(evt)
{
var tmp;
if(z == null)
return;
evt = (evt)?evt:((window.event)?window.event:null);
tmp = z.firstChild;
while((tmp != null) && (tmp.tagName != 'DIV'))
tmp = tmp.firstChild;
if(tmp != null)
{
if (selected)
{
tmp.className = "rowbox a";
selected = false;
} else
{
tmp.className = "rowbox selecteda";
selected = true;
}
}
}
I think your problem is that the 2nd click is registering as a dblclick event, not as a click event. The change is happening quickly, but the 2nd click is ignored unless you wait. I would suggest changing to either the mousedown or mouseup event.
I believe your problem is the changing of the innerHTML which changes the DOM which is a huge performance problem.
Yeah you may want to compare the performance of innerHTML against document.createElement() or even:
el.style.display = 'block' // turn off display: none.
Profiling your code may be helpful as you A/B various refactorings:
http://www.mozilla.org/performance/jsprofiler.html
http://developer.yahoo.com/yui/profiler/
http://weblogs.asp.net/stevewellens/archive/2009/03/26/ie-8-can-profile-javascript.aspx

Categories

Resources