Onclick javascript function working only on second click - javascript

function toggleDivFunction() {
var arrowElement = document.getElementById("arrowRight");
var showElement = document.getElementById("dropdownText");
arrowElement.onclick = function() {
if (showElement.style.display == 'none') {
showElement.style.display = 'block';
document.getElementById("arrowRight").style = "transform: rotate(+90deg)";
} else {
showElement.style.display = 'none';
document.getElementById("arrowRight").style = "transform: rotate(0deg)";
}
}
}
<p class="dropdownHeader">TOP <span id="arrowRight" class="arrowRight" onclick="toggleDivFunction();"> > </span></p>
<div class="dropdownText" id="dropdownText"><p>TEXT TO BE SHOWN</p></div>
The problem is that the dropdownText div only shows up after a second click on the arrowRight span.
I have seen it as a common problem, but still failed in finding a solution. Any help would be appreciated.

You do not need to bind a click event handler inside another click event handler. You have to use a single click event handler.
The show/hide functionality belongs to second click event handler and this is binded to your span DOM element after first click.
function toggleDivFunction () {
var arrowElement = document.getElementById ("arrowRight");
var showElement = document.getElementById ("dropdownText");
if(showElement.style.display == 'none')
{
showElement.style.display = 'block';
document.getElementById("arrowRight").style = "transform: rotate(+90deg)";
}
else
{
showElement.style.display = 'none';
document.getElementById("arrowRight").style = "transform: rotate(0deg)";
}
}
<p class="dropdownHeader">TOP <span id="arrowRight" class="arrowRight" onclick="toggleDivFunction();"> > </span></p>
<div class="dropdownText" id="dropdownText">
<p>TEXT TO BE SHOWN</p></div>

Just adding to approved answer.
Check for showElement.style.display == ''.
Additionally, for switching to flex on first click itself, if you are using display = 'none' as default.
Example:
..
if (showElement.style.display == 'none' || showElement.style.display == '') {
..
if the style of text is display = 'none'.

You want to assign your event handlers earlier:
window.onload=toggleDivFunction;
and remove the onclick='toggleDivFunction()', its unneccessary then and oldfashioned.
Your code assigns a listener when an event is triggered (toggleDivFunction). To trigger the listener (arrowElement.onclick) you need to cause another event doing a second click.

remove the arrowElement.onclick = function() {}
Why?
you have already apply the function in onclick=toggleDivFunction() with arrowRight .so
first execute the toggleDivFunction() then to perform the Dom arrowElement.onclick .use any one of the onclick function ,not both
function toggleDivFunction() {
var arrowElement = document.getElementById("arrowRight");
var showElement = document.getElementById("dropdownText");
if (showElement.style.display == 'none') {
showElement.style.display = 'block';
document.getElementById("arrowRight").style = "transform: rotate(+90deg)";
} else {
showElement.style.display = 'none';
document.getElementById("arrowRight").style = "transform: rotate(0deg)";
}
}
<p class="dropdownHeader">TOP <span id="arrowRight" class="arrowRight" onclick="toggleDivFunction();"> > </span></p>
<div class="dropdownText" id="dropdownText">
<p>TEXT TO BE SHOWN</p>
</div>

Related

JavaScript and HTML to show or hide an element

I think this is very easy, but I just can't seem to twig it at the moment. I want to use a JavaScript function to set the visibility of an HTML tag.
I realise the below is wrong as hidden doesn't take a boolean. I'm just struggling to click what the easiest way to do it is?
So I have some script like this:
<script>
function evaluateBoolean() {
if (location.hostname.indexOf("someval" > 0) {
return true;
} else {
return false;
}
}
</script>
And I wanted to use it something like this:
<div hidden="evaluateBoolean()">
this will be shown or displayed depending on the JavaScript boolean
</div>
I would recommend doing it by altering the display style in the JavaScript code.
const el = document.getElementById('container');
const btn = document.getElementById('btn');
btn.addEventListener('click', function handleClick() {
if (el.style.display === 'none') {
el.style.display = 'block';
btn.textContent = 'Hide element';
} else {
el.style.display = 'none';
btn.textContent = 'Show element';
}
});
You have a div with id: myDIV
<div id="myDIV" class="card-header">
Hello World
</div>
You then call this Javascript function to show the element:
function showDiv() {
document.getElementById('myDIV').style.display = "block";
}
and this one to hide it:
function hideDiv() {
document.getElementById('myDIV').style.display = "none";
}
Note, that you can hide a div by:
<div id="myDIV" class="card-header" style="display:none">
Hello World
</div>
And then call the function to show it.
You trigger must be outside of the element which you hide. because if hided you cant even clicked. The js function classList toggle would be good.
function evaluateBoolean() {
const d = document.querySelector('.w div');
d.classList.toggle('hide');
}
.w {
height: 40px;
background: yellow;
}
.hide {
display: none;
}
<div class="w" onclick="evaluateBoolean()">
<div> this will be shown or displayed depending on the javascript boolean </div>
</div>
You can't explicitly run js in your html, if you aren't using any framework like angular or react, where property binding is allowed.
For achieving your intentions with js you can use this approch:
Add to your div an id:
<div id="myDiv"> Toggled div </div>
In your js script modify your function evaluateBoleean() to show/hide the element:
function evaluateBoolean() {
const div = document.querySelector("#myDiv");
if (location.hostname.indexOf("someval" > 0) {
div.hidden = true;
} else {
div.hidden = false;
}
There's a very easy option:-->
having a blank text
firsly replace the html code with this:-->
<div hidden="evaluateBoolean()" id="ThingToBeHidden"> this will be shown or displayed depending on the javascript boolean </div>
and put js code:-->
document.getElementById("ThingToBeHidden").innerHTML = "";
So you have assigned the div to have it's special id which none other element has.
So now the js code selects the div with that id and then sets the context of it to blank.
If you want the text to appear again, the js code is:-->
document.getElementById("ThingToBeHidden").innerHTML = "this will be shown or displayed depending on the javascript boolean";
You can hide an element in several ways (using jQuery):
const o = $(cssSelectorForElementToStyle);
$(o).hide();
$(o).toggle();
$(o).css('display', 'none');
$(o).addClass('css_class_for_hiding_stuff');
Here using vanilla JavaScript:
const o = document.querySelector(cssSelectorForElementToStyle);
o.style.display = 'none';
o.classList.add('css_class_for_hiding_stuff');
But your question doesn't point out exactly when you are going to make this check. So let's assume you are going to check the boolean value once when the page is loaded and hide or show a given element according to that value:
$(document).ready(
() => {
if (evaluateBoolean() === true) {
// do nothing in this case
} else {
$('#elementWithThisId').css('display', 'none');
}
}
);
Without jQuery:
document.addEventListener("DOMContentLoaded", function() {
if (evaluateBoolean() === true) {
// do nothing in this case
} else {
document.querySelector('#elementWithThisId').style.display = 'none';
}
});

Why do I have to click twice for this JavaScript function to work?

In order for the fucntion to change the display to "hidden" then back to "block" it requires 2 clicks for each. Why is this? How do I reduce it to just one click?
function showOfferMessage() {
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
}
<div class="offer-row collapsible" id="'.$oid.'" onclick="showOfferMessage()">
<div class="offer-info-item">
<div class="offcatreview-title">
<h3>Cat. Rating</h3>
</div>
<div class="offer-cat-rating">
</div>
</div>
</div>
<div class="content">
<p>'.$message.'</p>
</div>
That's because you're registering an event listener on every click! So your listener executes once more every time you click.
Your code fixed:
function showOfferMessage(element) {
element.classList.toggle("active");
var content = element.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
}
<div class="offer-row collapsible" id="'.$oid.'" onclick="showOfferMessage(this)">
<div class="offer-info-item">
<div class="offcatreview-title">
<h3>Cat. Rating</h3>
</div>
<div class="offer-cat-rating">
</div>
</div>
</div>
<div class="content" style="display: block">
<p>'.$message.'</p>
</div>
The onclick event executes the showOfferMessage() {} function which puts an event listener on the "collapsible" element. Then the second click executes the contents of the eventlistener.
But first thing first, as long as you only have a single element named "collapsible" why try to get multiple elements. Do a document.querySelector and target the element using css style selectors then chain the addEventListener directly on that selector.
When you are querying the style like you do you get the style that was explicitly set. In your case if there has not been a click on the "collapsible" element no display style was set. And even though a div has a default display style of block it has not been explicitly set so ...style.display will return an empty string -> falsy.
You have to get the implicit style with the getComputedStyle method,
Like so (codepen):
document.querySelector(".collapsible").addEventListener("click", function() {
this.classList.toggle("active");
var content = document.querySelector(".content");
if (window.getComputedStyle(content).display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
And I would probably use an arrow function in the event listener:
document.querySelector(".collapsible").addEventListener("click", event => {
event.target.classList.toggle("active");
var content = document.querySelector(".content");
if (window.getComputedStyle(content).display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
I had similar problem and ended up using !== instead of ===:
if (content.style.display !== "none") {
content.style.display = "none";
} else {
content.style.display = "block";
};

how to show the sub elements text based on div>a like the select>option structure in a drop-down box using original javascript

everyone. I got some problems when I wanna accomplish a drop-down box in a HTML website without using select and option elements, instead of using and elements.
The main function is made up by two parts, the first function is when clicked the first elements in the drop-down box, the hidden parts of list shows up and hide clicked again. The second function is when choose the elements in the hidden list, the text of the elements on the list will replace the first element on the drop-down box.
I have accomplished first function using below codes:
// javascript codes
var searchListBtn = document.getElementById("btn_List");
var a_searchListBtn = document.getElementById("btn_List").getElementsByTagName("a");
function show(event) {
let oevent = event || window.event;
if (document.all) {
oevent.cancelBubble = true;
}
else {
oevent.stopPropagation();
}
// click it to show it, click again to hide it and loop
if (searchListBtn.style.display === "none" || searchListBtn.style.display === "") {
searchListBtn.style.display = "block";
}
else {
searchListBtn.style.display = "none";
}
}
document.onclick = function() {
searchListBtn.style.display = "none";
}
searchListBtn.onclick = function (event) {
let oevent = event || window.event;
oevent.stopPropagation();
}
<!-- html codes -->
<html>
<body>
<div>
<div class="ui-search-selected" onclick="show();">A</div>
<div class="ui-search-selected-list" id="btn_List">
B
C
D
</div>
</div>
</body>
</html>
But when I did the second part, my idea was not clear enough to implement that, I searched if I use select>option elements I could use selectedIndex method to find the index of list, but this is a custom drop-down box formed by div>a structure elements.
I tried to console.log(a_searchListBtn) and show an array from the console, and I could use a_searchListBtn[0~3].text to get the value of B/C/D.
I tried to write codes like below:
a_searchListBtn.onclick = function() {
console.log("Clicked.")
}
But nothing in the console, so, is there anyone could apply some help, thx in advance.
Well you're fetching all the a elements using getElementsByTagName("a"). Now you just need to loop through the results and add a click event listener that will take the innerHTML of that a element and put it into the innerHTML of the ui-search-selected div.
You don't need an index. You can access the clicked element's innerHTML using event.target. See it working in this snippet below:
// javascript codes
var searchListBtn = document.getElementById("btn_List");
var uiSearchSelected = document.getElementById("ui-search-selected");
var a_searchListBtn = document.getElementById("btn_List").getElementsByTagName("a");
for (button of a_searchListBtn) {
button.addEventListener("click", replace);
}
function show(event) {
let oevent = event || window.event;
if (document.all) {
oevent.cancelBubble = true;
}
else {
oevent.stopPropagation();
}
// click it to show it, click again to hide it and loop
if (searchListBtn.style.display === "none" || searchListBtn.style.display === "") {
searchListBtn.style.display = "block";
}
else {
searchListBtn.style.display = "none";
}
}
document.onclick = function() {
searchListBtn.style.display = "none";
}
searchListBtn.onclick = function (event) {
let oevent = event || window.event;
oevent.stopPropagation();
}
function replace(event) {
if (!event) return;
uiSearchSelected.innerHTML = event.target.innerHTML
}
<!-- html codes -->
<html>
<body>
<div>
<div id="ui-search-selected" onclick="show();">A</div>
<div class="ui-search-selected-list" id="btn_List">
B
C
D
</div>
</div>
</body>
</html>
I have tried to use this codes to implement this funtion, it works.
// javascript
var par_searchListBtn = document.getElementById("btn_list_parent");
var searchListBtn = document.getElementById("btn_List");
var a_searchListBtn = document.getElementById("btn_List").getElementsByTagName("a");
// console.log(a_searchListBtn.length);
// console.log(a_searchListBtn);
function show(event) {
let oevent = event || window.event;
if (document.all) {
oevent.cancelBubble = true;
}
else {
oevent.stopPropagation();
}
if (searchListBtn.style.display === "none" || searchListBtn.style.display === "") {
searchListBtn.style.display = "block";
}
else {
searchListBtn.style.display = "none";
}
}
document.onclick = function() {
searchListBtn.style.display = "none";
}
searchListBtn.onclick = function (event) {
let oevent = event || window.event;
oevent.stopPropagation();
}
for(var i = 0; i < a_searchListBtn.length; i++){
a_searchListBtn[i].onclick = function () {
par_searchListBtn.innerHTML = this.innerText;
//searchListBtn.style.display = "none";
}
}
<!-- html codes -->
<html>
<body>
<div>
<div class="ui-search-selected" id="btn_list_parent" onclick="show();">A</div>
<div class="ui-search-selected-list" id="btn_List">
B
C
D
</div>
</div>
</body>
</html>

Javascript click event requires double clicks

I have a simple HTML-CSS-JavaScript page with an event listener on a button to toggle a div.
However, all is working but the animation function takes two clicks first time to work, although i consoled the click event to prove that the button listens to the first click too.
i tried to wrap into window.onload but same thing.
note: i want to use pure javascript only.
thank you
this pic shows the first click (it says "clicked" in the console):
this pic shows the second click (animation took place):
Here is my code:
var showDivButton = document.getElementById('showDivButton');
var info = document.getElementById('info');
showDivButton.addEventListener('click', animation) ;
// animation func
function animation () {
console.log('Clicked!');
if (info.style.display === 'none'){
info.style.display = 'inline-block';
showDivButton.style.background = 'green';
} else {
info.style.display = 'none';
showDivButton.style.background = 'gray';
}
}
Look at My Plunker Here please. Thank you in advance.
Try to revise your function block as follow:
function animation () {
console.log('Clicked!');
if (info.style.display == '' || info.style.display == 'none'){
info.style.display = 'inline-block';
showDivButton.style.background = 'green';
} else {
info.style.display = 'none';
showDivButton.style.background = 'gray';
}
}
info.style.display is '' on initial
Because info.style.display refers to the style attribute of your div, not the computed Style, so on the first click, this is not set.
You may want to look at getComputedStyle, but i would advise switching class instead of directly modifying style.

double click to show an div

I have used a javascript to show div by onclick but when i click outside div i want to hide the div.
after more searches, i have found an function, and it works perfectly
but there is an issue, the code requires double click for first time, to show the dive
my code:
<script>
// click on the div
function toggle( e, id ) {
var el = document.getElementById(id);
el.style.display = ( el.style.display == 'none' ) ? 'block' : 'none';
// save it for hiding
toggle.el = el;
// stop the event right here
if ( e.stopPropagation )
e.stopPropagation();
e.cancelBubble = true;
return false;
}
// click outside the div
document.onclick = function() {
if ( toggle.el ) {
toggle.el.style.display = 'none';
}
}
</script>
<style>#tools{display:none;}</style>
<div id="tools">Hidden div</div>
show/hide
This is my full code, you can test it on your computer.
The question is: The function requires two clicks, i want show the div on click ( one click ) Not ( Double Click )
Try this - http://jsfiddle.net/JjChY/1/
Change
el.style.display = ( el.style.display == 'none' ) ? 'block' : 'none';
to
el.style.display = (el.style.display == 'none' || el.style.display == '') ? 'block' : 'none';
Use this:
el.style.display = window.getComputedStyle(document.getElementById("tools")).getPropertyValue("display") == "none" ? 'block' : 'none';
It should work.
The problem is that el.style.display only reads from the element's inline styles, not its CSS.
So, on the first click el.style.display is '' (blank string), so it's set to 'none'. Then the second time, el.style.display is 'none', so it works.
You need to try to read from the element's CSS if its inline styles are blank. I'm going to use the getStyle method from quirksmode for this:
function getStyle(x, styleProp) {
if (x.currentStyle) {
var y = x.currentStyle[styleProp];
}
else if (window.getComputedStyle) {
var y = document.defaultView.getComputedStyle(x, null).getPropertyValue(styleProp);
}
return y;
}
// click on the div
function toggle(e, id) {
var el = document.getElementById(id);
var display = el.style.display || getStyle(el, 'display');
el.style.display = (display == 'none') ? 'block' : 'none';
// save it for hiding
toggle.el = el;
// stop the event right here
if (e.stopPropagation) e.stopPropagation();
e.cancelBubble = true;
return false;
}
// click outside the div
document.onclick = function() {
if (toggle.el) {
toggle.el.style.display = 'none';
}
}​
DEMO: http://jsfiddle.net/JjChY/2/
Your code is a little convoluted. It can be written much simpler:
<script>
var toggle = function(id) {
var element = document.getElementById(id);
element.className = element.className === 'hidden' ? '' : 'hidden';
return false;
};
</script>
<style>
.hidden {
display: none;
}
</style>
<div id="tools" class="hidden">Hidden div</div>
show/hide
If you have jQuery, you could do something like this for the click outside.
First, set a class on the "tools" div when the mouse is inside it. Remove the class when the mouse is not inside it.
$('#tools').hover( function() {
$('#tools').addClass("inside");
},
function() {
$('#tools').removeClass("inside");
});
Then, track clicks on the HTML. Hide if the "inside" class is not on the "tools" div.
$("html").click( function() {
$("#tools").not(".inside").each( function() {
$("#tools").hide();
});
});

Categories