onClick event calling function, but not firing - javascript

Okay, so I'm getting a weird problem with my onClick elements.
I'm using PHP to echo some code, and here it is:
<div class = \"dropdown\">
<i id = \"elipses_$id\" onClick = \"dropDown_$id()\" style = \"color:#777\" class=\"fas fa-ellipsis-v\"></i>
<div id = \"dropdown_$id\" class = \"dropdown-content\">
[html code here isn't relevant]
</div>
</div>
When I open inspect element, and I click the button, it outputs the function name:
And when I type the function name into the console, the dropdown opens like it should. So why doesn't it do it when I click?
Not sure if it is needed, but here is the script I am using to open/close the dropdown.
function dropDown_$id() {
document.getElementById(\"dropdown_$id\").classList.toggle(\"show\");
}
window.onclick = function(event) {
console.log(event.target);
if (!event.target.matches('#dropdown_$id') && !event.target.matches('#elipses_$id')) {
var dropdown = document.getElementById(\"#dropdowm_$id\");
var c;
if(dropdown != null){
for (c = 0; c < dropdown.length; c++) {
var openDropdowns = dropdown[c];
if (openDropdowns.classList.contains('show')) {
openDropdowns.classList.remove('show');
}
}
}
}
}
EDIT: This is the raw HTML of the dropdown that is spat out after PHP is run:
<div id="dropdown_26" class="dropdown-content">
<div id="names" style="border-bottom: thin solid #BDBDBD;">
<h2 class="dropdown-contenth2">Francois van Kempen</h2>
<p style="color:grey;margin-top:-20px; margin-left: 16px;">#Bork_Bork</p>
</div>
div id="settings" style="border-bottom: thin solid #BDBDBD;">
<a id="a1" class="dropdown-contenta" href="settings.php">Accout Settings</a>
<form id="dark_mode_form" action="nightmode.php" method="POST" style="padding: 10px; display:flex;justify-content:flex-start;align-content:center">
<label style="" class="switch">
<input onchange="this.form.submit()" type="checkbox" name="darkmode" value="checked">
<span class="slider round"></span>
</label>
<p class="dropdown-contentp" style="margin:0;padding:0; margin-left:5px;margin-top:5px;">Night mode</p>
</form>
</div>
<a id="a2" class="dropdown-contenta" href="logout.php">Log out #Bork_Bork</a>
<a id="a3" class="dropdown-contenta" href="reset-password.php">Reset password #Bork_Bork</a>
</div>
EDIT 2: Added the raw script:
<script id="dropdown-settings" type="text/javascript">
function dropDown() {
document.getElementById("dropdown").classList.toggle("show");
}
function dropDown_26() {
document.getElementById("dropdown_26").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
console.log(event.target);
if (!event.target.closest('#dropdown') && !event.target.closest('#navPFP')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
if (!event.target.matches('#dropdown_26') && !event.target.matches('#elipses_26')) {
var dropdown = document.getElementById("#dropdowm_26");
var c;
if(dropdown != null){
for (c = 0; c < dropdown.length; c++) {
var openDropdowns = dropdown[c];
if (openDropdowns.classList.contains('show')) {
openDropdowns.classList.remove('show');
}
}
}
}
}
</script>

Related

Trouble getting event listener to work properly in javascript

So I am a javascript noob. I'm doing an assignment for a webdesign class and we are practicing event listeners. So I had to assign variables to 3 separate divs, place them in an array, create a function to make them display or be hidden, and use a button/click event listener to call the function to call or hide them respectively. this is my code:
var greenBox = document.getElementById("greenBox");
var redBox = document.getElementById("redBox");
var blueBox = document.getElementById("blueBox");
var showALL = document.getElementById("showAll");
var hideALL = document.getElementById("hideAll");
var boxes = [greenBox, redBox, blueBox];
function showBoxes(boxes) {
for (i = 0; i < boxes.length; i++) {
boxes[i].style.display = "block";
}
}
function hideBoxes(boxes) {
for (i = 0; i < boxes.length; i++) {
boxes[i].style.display = "none";
}
}
showALL.addEventListener("click", function() {
showBoxes(boxes);
})
// The "Hide All" button invokes the hideBoxes method
hideALL.addEventListener("click", function() {
hideBoxes(boxes);
})
<form action="#">
<input type="button" id="showAll" value="Show All"><br />
<input type="button" id="hideAll" value="Hide All"><br />
</form>
<div class="box" id="greenBox" style="display:none"></div>
<div class="box" id="redBox" style="display:none"></div>
<div class="box" id="blueBox" style="display:none"></div>
So what the heck am I doing wrong? I've checked multiple times for typos, etc. but everything looks ok to me? It's still not working though.
document.getElementById is case-sensitive.
You have id="showAll" when you are searching for document.getElementById("showALL");.
Pick a consistent case and it should work.
var greenBox = document.getElementById("greenBox");
var redBox = document.getElementById("redBox");
var blueBox = document.getElementById("blueBox");
var showALL = document.getElementById("showAll");
var hideALL = document.getElementById("hideAll");
var boxes = [greenBox, redBox, blueBox];
function showBoxes(boxes) {
for (i = 0; i < boxes.length; i++) {
boxes[i].style.display = "block";
}
}
function hideBoxes(boxes) {
for (i = 0; i < boxes.length; i++) {
boxes[i].style.display = "none";
}
}
showALL.addEventListener("click", function() {
showBoxes(boxes);
})
// The "Hide All" button invokes the hideBoxes method
hideALL.addEventListener("click", function() {
hideBoxes(boxes);
})
.box {width: 200px; height: 36px;}
#redBox {background-color: #F00;}
#greenBox {background-color: #0F0;}
#blueBox {background-color: #00F;}
<form action="#">
<input type="button" id="showAll" value="Show All"><br />
<input type="button" id="hideAll" value="Hide All"><br />
</form>
<div class="box" id="greenBox" style="display:none"></div>
<div class="box" id="redBox" style="display:none"></div>
<div class="box" id="blueBox" style="display:none"></div>
Aside from your initial typo of the div ids document.getElementById("showALL"); should be document.getElementById("showAll");, the divs would also not appear without a size or contents. Something like this should do:
var greenBox = document.getElementById("greenBox");
var redBox = document.getElementById("redBox");
var blueBox = document.getElementById("blueBox");
var showALL = document.getElementById("showAll");
var hideALL = document.getElementById("hideAll");
var boxes = [greenBox, redBox, blueBox];
function showBoxes(boxes) {
for (i = 0; i < boxes.length; i++) {
boxes[i].style.display = "block";
}
}
function hideBoxes(boxes) {
for (i = 0; i < boxes.length; i++) {
boxes[i].style.display = "none";
}
}
showALL.addEventListener("click", function() {
showBoxes(boxes);
});
hideALL.addEventListener("click", function() {
hideBoxes(boxes);
});
<form action="#">
<input type="button" id="showAll" value="Show All"><br />
<input type="button" id="hideAll" value="Hide All"><br />
</form>
<div class="box" id="greenBox" style="display:none;background-color:green;height:20px;width:20px"></div>
<div class="box" id="redBox" style="display:none;background-color:red;height:20px;width:20px"></div>
<div class="box" id="blueBox" style="display:none;background-color:blue;height:20px;width:20px"></div>
The Problem is here in your Selectors
var showALL = document.getElementById("showALL");
var hideALL = document.getElementById("hideALL");
your Element is named "showAll" and you are using "showALL". Notice the capital "L".
As others have said your casing needs to be consistent. One thing that may help you out when debugging this sort of thing is to open up developer tools in your browser(f12 in chrome) and placing breakpoints in the javascript so you can step through and see what the values of your variables are.

JS functions to remove two different classes interfering with one another [duplicate]

This question already has answers here:
How to call multiple JavaScript functions in onclick event?
(14 answers)
Closed 5 years ago.
I have two JS functions:
function myFunctionMenu() {
document.getElementById("main-menu").classList.toggle("shows");
}
and
function expandFunction() {
document.getElementById("menu-button").classList.toggle("expand");
}
Both of which toggle classes. Those classes have styles:
.shows {
margin-right: auto;
margin-left: auto;
display: block;
transition: all 2s ease;
}
and
.expand {
padding: 1% 20%;
background-color: #8c8c8c;
}
I then have two more functions, one for each of those original functions, which removes that class when clicking outside of the button that initiates both functions:
window.onclick = function(event) {
if (!event.target.matches('#menu-button')) {
var dropdowns = document.getElementsByClassName("house-menu");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('shows')) {
openDropdown.classList.remove('shows');
}
}
}
}
and
window.onclick = function(event) {
if (!event.target.matches('#menu-button')) {
var dropdowns = document.getElementsByClassName("dropbtn");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('expand')) {
openDropdown.classList.remove('expand');
}
}
}
}
The HTML follows, just in case:
<!doctype html>
<head>
<title>Site Photos</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="Styles/new-menu.css">
<script type="text/javascript" src="script/menu-scripts.js"></script>
</head>
<body>
<br>
<h1>
Name <br>
</h1>
<h2>
Site Photos
</h2>
<!--Menu-->
<div class="menu-container" div style="margin-left:auto; margin right:auto; margin-top:5%; margin-bottom:auto; width:40%;">
<!-- Main Menu Button -->
<div id="main-button-container" style="text-align:center; margin-top:-8%;">
<button onclick="myFunctionMenu();expandFunction()" class="dropbtn" id="menu-button"> Menu </button>
</div>
<hr>
<!-- Main Menu Container -->
<div id="main-menu" class="house-menu">
Main House <hr>
Car Barn <hr>
Utility Building <hr>
Central Plant <hr>
Exteriors<hr>
</div>
<hr>
</div>
</body>
</html>
The problem I am having is that I can only run one of the two "remove when click outside the button" functions at a time.
Can anyone explain to me why?
Thank you.
Because the first window.onclick will get overridden by the second one. Just like writing var a = 1; and later var a = 2;. You should use document.addEventListener for this purpose:
document.addEventListener("click", function(e){
if (!e.target.matches('#menu-button')) {
var dropdowns = document.getElementsByClassName("house-menu");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('shows')) {
openDropdown.classList.remove('shows');
}
}
}
});
and
document.addEventListener("click", function(e){
if (!e.target.matches('#menu-button')) {
var dropdowns = document.getElementsByClassName("dropbtn");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('expand')) {
openDropdown.classList.remove('expand');
}
}
}
});

How to show emojis on my website?

When the user clicks the drop down menu, I want to show emojis. But the problem is the only way I know how to do that is to input an emoji one by one.
My question is how do I show all the emojis? I want to when the user clicks the drop down menu and when they click the emoji, add it to the text area.
home.php:
<textarea id="textf2" rows="3" maxlength="3000" placeholder="Enter text" cols="35">
</textarea>
<button id="bt6" type="submit" name="search">Post status</button>
<div class="dropdown" id="div1">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
<div id="myDropdown" class="dropdown-content">
</div>
</div>
<script>
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
</script>
Okay, I think this is what you want:
After looking here and tinkering with the code for an hour, I got this:
emojis = document.getElementById("myDropdown").getElementsByTagName("li")
for (var i = 0; i < emojis.length; i++) {
emojis[i].addEventListener("click", function() {
var smiley = this.innerHTML;
ins2pos(smiley, 'textf2');
});
}
function ins2pos(str, id) {
var TextArea = document.getElementById(id);
var val = TextArea.value;
var before = val.substring(0, TextArea.selectionStart);
var after = val.substring(TextArea.selectionEnd, val.length);
TextArea.value = before + str + after;
setCursor(TextArea, before.length + str.length);
}
function setCursor(elem, pos) {
if (elem.setSelectionRange) {
elem.focus();
elem.setSelectionRange(pos, pos);
} else if (elem.createTextRange) {
var range = elem.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn') && !event.target.matches('#myDropdown li')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
for (var i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
#myDropdown {
display: none
}
#myDropdown.show {
display: block;
}
<textarea id="textf2" rows="3" maxlength="3000" placeholder="Enter text" cols="35">
</textarea>
<button id="bt6" type="submit" name="search">Post status</button>
<div class="dropdown" id="div1">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
<ul id="myDropdown" class="dropdown-content">
<li>&#x1F601</li>
<li>&#x1F603</li>
<li>&#x1F605</li>
</ul>
</div>
JSfiddle and more emojis here
Hope that helps!
Update: To include images, you got to use <div id="textf2" contentEditable="true"></div> instead of the text area and use the code noted here
emojis = document.getElementById("myDropdown").getElementsByTagName("li")
for (var i = 0; i < emojis.length; i++) {
emojis[i].addEventListener("click", function() {
var smiley = this.innerHTML;
pasteHtmlAtCaret(smiley + " ");
});
}
function pasteHtmlAtCaret(html) {
var sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// only relatively recently standardized and is not supported in
// some browsers (IE9, for one)
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn') && !event.target.matches('#myDropdown img')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
for (var i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
#myDropdown {
display: none
}
#myDropdown.show {
display: block;
}
#text_wrapper {
margin: 40px;
border: 1px solid #ccc;
}
#textf2 {
outline: none;
margin: 10px;
min-height: 100px;
}
img {
width: 50px;
height: auto;
}
<div id="text_wrapper">
<div id="textf2" contentEditable="true">
</div>
</div>
<button id="bt6" type="submit" name="search">Post status</button>
<div class="dropdown" id="div1">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
<ul id="myDropdown" class="dropdown-content">
<li><img src="https://upload.wikimedia.org/wikipedia/commons/e/ec/Happy_smiley_face.png" /></li>
<li><img src="http://res.freestockphotos.biz/pictures/15/15550-illustration-of-a-yellow-smiley-face-pv.png" /></li>
<li><img src="http://res.freestockphotos.biz/pictures/15/15564-illustration-of-a-yellow-smiley-face-pv.png" /></li>
</ul>
</div>
EDIT: I misread the question, so I'll add in how I would do it:
I would create an array of Emoji characters. I would then loop over this array of emojis. For each emoji in the array you want to perform a 'map' operation so you get an HTML element. Then you want to append these elements to the dropdown-content element as children.
For example:
var emojis = ['😍','😀','🤑']; // put all emojis in here
emojis.map((character) => {
var a = document.createElement('a');
a.src='#';
a.textContent = character;
a.addEventListener(
'click',
function() { /* append character to the textarea. this will probably something simple like 'textareaElement.value += character */}
);
return a;
});
emojis.forEach((el) => dropDownContentElement.appendChild(el));

How to count dynamically div display block?

I have 3 div. 2 are hidden by default.
By clicking on a link "add" or a link "remove", I want the other div to be shown or hidden. And then, I would like to count dynamically div which are shown.
Here is my HTML :
<div id="clone1" class="billet">
<input type="text" /><span id="test"></span>
</div>
<div id="clone2" class="billet" >
<input type="text" />
</div>
<div id="clone3" class="billet" >
<input type="text" />
</div>
<div id="ajout-suppr">
<a href="javascript:;" class="ajoutBillet" >Ajouter un billet</a>
<span>-------------</span>
<a href="javascript:;" class="supprBillet" >Supprimer un billet</a>
</div>
jQuery :
$(document).ready(function () {
$(".supprBillet").hide();
$("#clone2").hide();
$("#clone3").hide();
$(".ajoutBillet").click(function (){
var nb = $('.billet:not([style*="display: none"])').size();
$('#test').html(nb);
if(nb < 2) {
$(".supprBillet").hide();
}
else {
$(".supprBillet").show("slow");
}
if($("#clone2").hide()) {
$("#clone2").show("slow");
}
if($("#clone3").hide() && $("#clone2").show()) {
$("#clone3").show();
}
if($("#clone3").show() && $("#clone2").show()) {
$(".ajoutBillet").hide("slow");
}
}); // fin du click function ajout billet
$(".supprBillet").click(function (){
var nb = $('.billet:not([style*="display: none"])').size();
if(nb < 2) {
$(".supprBillet").hide();
}
else {
$(".supprBillet").show();
}
if($("#clone2").show() && $("#clone3").hide()) {
$("#clone2").hide();
}
}); // fin du click function suppr billet
});
As you see nothing works.
Could you please show me an issue?
Thanks in advance.
you can try something like this:
jQuery('.ajoutBillet').on('click',function(){
var lengthDivs = jQuery('.billet:visible').length;
if(lengthDivs < 2 && jQuery('.supprBillet:visible').length > 0){
jQuery('.supprBillet').hide();
}
});
I made this into a fiddle. This does seem to do what is expected (by code). Are you referencing the jquery library?
I did make some changes to your count by checking on 1
if(nb < 1) {
$(".supprBillet").hide();
}
You need to check the visible div by jquery .is(':visible') function.
Like this way :
Replace this
var nb = $('.billet:not([style*="display: none"])').size();
With
var nb = $('.billet').is(":visible").length;
Now shows and hides the inputs:
$(document).ready(function() {
$(".billet input:nth-child(1)").hide();
$(".billet input:nth-child(2)").hide();
$("#new").click(function() {
var count = 0;
$(".billet input").each(function() {
if ($(this).is(":visible")) {
count++;
}
});
$(".billet input:nth-child("+count+")").show();
if ($("#total-divs").html() < 3) {
$("#total-divs").html(count+1);
}
});
$("#delete").click(function() {
var count = -1;
$(".billet input").each(function() {
if ($(this).is(":visible")) {
count++;
}
});
if (count > 0) {
$(".billet input:nth-child("+count+")").hide();
$("#total-divs").html(count);
}
});
});
input {
margin: 4px 0;
width: 100%;
}
.actions {
display: block;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="billet" >
<input type="text" />
<input type="text" />
<input type="text" />
</div>
<div class="actions">
New | Delete
</div>
Total: <span id="total-divs">1</span>

JavaScript Toggle Display

I'm trying to use vanilla JavaScript to toggle display: none and display: block on elements with the same class. It mostly works, but for some reason you need to click the button twice for it to work and it's eating away at me. The code and a link to CodePen is below.
The HTML:
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<div class="d">d</div>
<button onclick="toggle('a')">Toggle A</button>
<button onclick="toggle('b')">Toggle B</button>
<button onclick="toggle('c')">Toggle C</button>
<button onclick="toggle('d')">Toggle D</button>
The JS:
function toggle(div) {
var divs = document.getElementsByClassName(div);
for(var i = 0; i < divs.length; i++) {
if(divs[i].style.display === "block") {
divs[i].style.display="none";
}
else {
divs[i].style.display="block";
}
}
}
The Demo:
CodePen
add the style attribute to the divs..
<div class="a" style="display:block">a</div>
<div class="b" style="display:block">b</div>
<div class="c" style="display:block">c</div>
<div class="d" style="display:block">d</div>
I would do this instead:
<div class='a'>a</div>
<div class='b'>b</div>
<div class='c'>c</div>
<div class='d'>d</div>
<input type='button' id='aT' value='Toggle A' />
<input type='button' id='bT' value='Toggle B' />
<input type='button' id='cT' value='Toggle C' />
<input type='button' id='dT' value='Toggle D' />
Put external JavaScript tag in <head> for caching:
var pre = onload;
onload = function(){
if(pre)pre();
var doc = document, bod = doc.body;
function E(e){
return doc.getElementById(e);
}
function C(n){
if(doc.getElementsByClassName){
return doc.getElementsByClassName(n);
}
var t = doc.getElementsByTagName('*'), a = [];
for(var i=0,l=t.length; i<l; i++){
if(t[i].className.match(new RegExp('\\b'+n+'\\b'))){
a.push(t[i]);
}
}
return a;
}
function getStyleProp(elem, prop){
return getComputedStyle(elem).getPropertyValue(prop) || elem.currentStyle[prop];
}
function toggle(elem){
elem.style.display = getStyleProp(elem, 'display').match(/^block$/i) ? 'none' : 'block';
return elem;
}
var btns = ['a', 'b', 'c', 'd'];
for(var i=0,l=btns.length; i<l; i++){
(function(i){
var b = btns[i], c = C(b);
E(b+'T').onclick = function(){
for(var n=0,q=c.length; n<q; n++){
toggle(c[n]);
}
}
})(i);
}
}
Add display: block; to the CSS definition for the DIV.
your var divs = document.getElementsByClassName(div); will only return one element because there is only one element with that class.
<div id="blocks'>
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<div class="d">d</div>
</div>
function toggle(div) {
var divs = document.getElementById('blocks');
var ele = blocks.getElementsByTagName("div');
var sty = "";
for(var i = 0; i < ele.length; i++) {
sty = ( ele[i].className.indexOf( div ) ) ? 'block' : 'none';
ele[i].style.display = sty;
}
}
}

Categories

Resources