Accordion closing onClick anywhere in container - javascript

I am trying to create an accordion for a project I'm working on. For the sake of argument, lets assume this accordion only has one container. So far, I've got it all working, however when I expand the accordion, which will only expend if I click on the header, I am then able to close the open container by clicking anywhere in the container, rather than just the header.
I've tried a few different things resulting in null .toggle errors so far. Below is a snippet of the accordion itself, along with the JS I'm using with it. Please bare in mind the accordion functions correctly and displays correctly, its the click function that's the issue (meaning my CSS is fine so no point sharing):
JS:
const accordion = document.getElementsByClassName('container1');
for (i=0; i<accordion.length; i++) {
accordion[i].addEventListener('click', function () {
this.classList.toggle('active');
});
}
Accordion HTML:
<div class="accordion-body">
<div class="accordion">
<hr>
<div class="container1" id="container1">
<div class="label" id="linkId">Generate a payment link</div>
<div class="content">
<div class="form">
</div>
</div>
</div>
<hr>
</div>
</div>
Essentially, I only even want the accordion to open/close if the 'label' div is pressed. This is because within my accordion there are buttons, so at the moment when a button is pressed when accordion is open, it changes the class which closes the accordion back up. Right now I understand that the clickable area is 'container1' but I've not been able to make it work against the label div.
I can also provide a link to the webpage where it is happening, happy to provide this via PM.
I tried changing the JS to the below:
const accordion = document.getElementsByClassName('container1');
const linkId = document.getElementById('linkId');
for (i=0; i<accordion.length; i++) {
document.getElementById('linkId').addEventListener('click', function () {
accordion.classList.toggle('active');
});
}
However the above produces the following error:
Uncaught TypeError: Cannot read properties of undefined (reading 'toggle')
at HTMLDivElement. (txninfo.php:825:25)
LINE 825 is the following:
accordion.classList.toggle('active');
Any help would be massively appreciated

accordion in that case is instance of HTML-Collection and not Element as you assume.
So you correctly iterate over the collection of elements, you now just want to select the current element (where key == i) of iteration instead of the whole collection.
accordion[i].classList.toggle('active');
then you should have an Element and should be able to access it´s properties like classList
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName

Related

Style sheet toggle doesn't work on both buttons

I'm trying to get my dark mode toggle button to function properly. It can work on EITHER mobile or desktop but not BOTH. I tried everything and search countless of information and can't find the answer. I'm not a developer and this is my first time with javascript. Any help or information would be helpful and appreciated. I want 2 buttons to toggle the single function of changing style sheets. I have 2 different navs, one for mobile and one for desktop (I don't know why but this is what I was taught in my web design class.)
I guess this is where I put my code. Sorry if I don't include all the information but I'll include what I think is relevant.
HTML:
<div class="col-3 col-3-tb d-none">
<div id="myDIV" class="btn-click" onclick=" myFunctiontext();">Dark<br>Mode<br>Enable</div>
</div>
<div class="switch">
<div id="myDIVmb" class="btn-push" onclick="myFunctiontextmb();">Dark Mode<br>Enable</div>
</div>
the classes are just margins to change up positions on the layout or the font.
Javascript:
// Select the button
const btn = document.querySelector(".btn-push, .btn-click");
// Select the stylesheet <link>
const theme = document.querySelector("#theme-link");
// Listen for a click on the button
btn.addEventListener("click", function() {
// If the current URL contains "ligh-theme.css"
if (theme.getAttribute("href") == "style-light.css") {
// ... then switch it to "dark-theme.css"
theme.href = "style-dark.css";
// Otherwise...
} else {
// ... switch it to "light-theme.css"
theme.href = "style-light.css";
}
});
Like I said I'm not a developer. I found the code from this website and tried it out.

Apply class to neighbor div when div gets class

I have a div containing all my content, and then I have a div containing pop-up windows. So basically something like this:
<div class="content">
Some content
</div>
<div class="popup-wrapper">
Popup content
</div>
Then at some point a class is added to the popup-wrapper due to some button click, that in Angular would look something like:
<button (click)="popup = !popup">Click me</button>
<div class="popup-wrapper" [ngClass]="popup ? 'is-active' : ''">
Popup content
</div>
My question is: Are there some way (CSS wise. JS would probably also do if no other alternative is available) that when popup-wrapper has the class is-active I can also target content as well ?
The issue for me not just putting the same JS into the content div, i.e. [ngClass]="popup ? 'is-active' : ''" is because there are several instances that can activate a popup, and other popup wrappers as well. So if I were to do this I would have to go through every page that has this kind of popup-wrapper, and paste similar code into every content div, but with different state names.
So I just thought it would be much easier, if I could target the content div whenever the popup-wrapper div had the is-active class.
For my understanding, you'll need something like that:
function anyName () {
let x = document.getElementByClassName('is-active');
if (x === true) {
// do something
}
}
Depending on what ever you want to do next, you can either go for an identifier like your div's className ('content') or you try to target it by its position, like 'previousElementSibling'

Issue with handling a form using javascript

We have a website hosted at hubspot, we use their native WYSIWYG to design layouts then style them with css and js.
On the homepage http://www.lspatents.com/ it used to have a form under the "Get started here" title, it had around 10 questions, and used javascript to split them to steps so they can fit in the same area on the currently shown blank box.
It was working just fine till two days ago the form disappeared and left it with a blank area as you can see now, and as far as i know no one has touched this code recently.
Here is the js code that was used to manipulate the form
// Hero Form
$(window).load(function() {
// disable autocomplete to fix bug
$('.hero-form form').attr("autocomplete", "off");
$('.hero-form .hs-richtext').each(function() {
$(this).nextUntil('.hs-richtext').wrapAll('<div class="step" />');
});
// Hide Loading icon
$('.hero-form form').css('background', 'none');
$('.hero-form form .step:nth-of-type(2)').show();
// First Step to Second Step
$('.step').find('.hs-richtext').change(function() {
$('.step:nth-of-type(2)').hide().next().next().fadeIn();
});
// Second Step to Third Step
$('.step').find('.hs-input').change(function() {
var names = {};
$(':radio').each(function() {
names[$(this).attr('name')] = true;
});
var count = 0;
$.each(names, function() {
count++;
});
if ($(':radio:checked').length === count) {
$('.step:nth-of-type(4)').hide().next().next().fadeIn();
}
});
});
As far as i was able to tell, the developer used css to hide the whole form area with display:none; and used the js above to split the questions to steps and show a certain number in each step.
You can see the code being called in the footer so there is no problem with the link to the .js file, also if you inspect the element and disable the display:none; that's declared for any of the divs within the hero-form all questions get displayed, so there is no problem with the form either, so why has it stopped working?
Would appreciate any help,
This line will no longer work with your mark-up...
$('.hero-form form .step:nth-of-type(2)').show();
There are a number of additional divs that wrap your mark-up, placed there by react, React has placed a series of div inside your form which are being hidden by your existing CSS (which I assume used to just be a series of STEP's)
The CSS that hides the nodes is :
.hero-form form>div, .hero-form form>.step {
display: none;
}
The nodes that are being hidden with display:none
<div data-reactid=".0.0:$1">
<div class="hs-richtext" data-reactid=".0.0:$1.0">
<hr>
</div>
<div class="step">
<div class="hs_patent field hs-form-field" data-reactid=".0.0:$1.$patent">
<label placeholder="Enter your Do you have a patent?" for="patent-9fc8dd30-a174-43bd-be4a-34bd3a00437e_2496" data-reactid=".0.0:$1.$patent.0">
<span data-reactid=".0.0:$1.$patent.0.0">Do you have a patent?</span>
<span class="hs-form-required" data-reactid=".0.0:$1.$patent.0.1">*</span>
</label>
<div class="hs-field-desc" style="display:none;" data-reactid=".0.0:$1.$patent.1">
</div>
</div>
Your JQuery will add display:block to the DIV with the class 'step' bit wont alter the parent DIV (inserted by React) which still prevents your node from being shown.
You need to alter you JQuery to call show() on the parent() that contains the "step" div you wish to show.
Please check your browser console ans see you have problem loading this form:
https://forms.hubspot.com/embed/v3/form/457238/9fc8dd30-a174-43bd-be4a-34bd3a00437e
and this is the error:
net::ERR_NAME_RESOLUTION_FAILED
It's better you change your DNS to something like 8.8.8.8 and see if the problem still exists or not.

How to get the div behind the div i clicked

Please take a look here at what I'm trying to achieve: http://jsfiddle.net/3m6r7ud2/4/
I have the following html page that looks like this:
<div class="page_conatiner" id="page1">
<img src=$file1>
<div class="page_conatiner" id="page2">
<img src=$file2>
<div class="page_conatiner" id="page3">
<img src=$file3>
And so on.
I also have a fixed button that shows up on hover:
<div class="rotate_button" id="rotate_left" ></div>
<div class="rotate_button" id="rotate_right" ></div>
This is the jQuery I'm using:
$(document).on("click", ".rotate_button", function(){
var direction = $(this).attr("id");
var page_num = ?
rotate_file(page_num,direction)
})
The buttons are in fixed locations on the page, and show on hover. When clicking on this button, I want to get which div was behind that div while clicking
so I could know which of the pages I need to rotate.
How can I do this?
First, I'm not certain what animation you are going for, but there might be a jQuery widget that will do what you want out of the box. Idk. The bootstrap one is handy, but maybe all of bootstrap is more than you want: http://getbootstrap.com/javascript/#carousel.
To answer your question: I would set a variable somewhere that keeps track of the current page num. Set it to 0 (or 1 if that's the first page number) when the page loads, and then in your click handler, increment it by 1. And then make sure to reset it to 0 (or 1) again when it gets high enough to start over. Does that answer your question?

JQuery .not(find()) or - can it be used?

I have the following html:
<div class="profileRowHeader"><!-- div 1 -->
<div class="folderIcon">
<i class="glyphicon glyphicon-arrow-close"></i>
</div>
</div>
<div class="profileRowHeader"><!-- div 2 -->
<div class="folderIcon">
<i class="glyphicon glyphicon-folder-open"></i>
</div>
</div>
<div class="profileRowHeader"><!-- div 3 -->
<div class="folderIcon">
<i class="glyphicon glyphicon-folder-close"></i>
</div>
</div>
When I click element with class .profileRowHeader, it does some stuff and changes the icon folder from closed to open. As in middle div above.
$this.find(".folderIcon").toggleClass('glyphicon-folder-open glyphicon-folder-close');
Works great. Now, if I click on div 3 above, div 2 still has icon folder-open, so to combat this i close all the folder icons whenever any profileHeaderRow is clicked.
$(".folderIcon").removeClass('glyphicon-folder-open').addClass('glyphicon-folder-close');
Problem of course is that i'm using toggleClass, so the icon within the div i'm clicking will go to closed, then will toggle itself open again.
So, can I somehow find the class folderIcon within the div I clicked and not apply the class change to it. Hope that makes sense.
This is what I'm trying but simply does not work:
$(".folderIcon").not(find(".folderIcon")).removeClass('glyphicon-folder-open').removeClass('greenDragBg').addClass('glyphicon-folder-close');
Full code as it is:
$('.profileRowHeader').click(function() {
$(".folderIcon").not(find(".folderIcon")).removeClass('glyphicon-folder-open').addClass('glyphicon-folder-close');
$this.find(".folderIcon").toggleClass('glyphicon-folder-open glyphicon-folder-close');
});
Summary: I have x number of divs with class profileRowHeader within each of them is a folder icon, all closed... when I click any of the divs with class profileRowHeader I want that icon to become open, the rest are closed. When I click that div again, it changes to closed icon. However, if it is left open and another div is clicked it should close the open one, and the new folder icon within the new profileRowHeader becomes open.
Hope that's a bit clearer
This is how you can find elements inside the clicked element:
$(".folderIcon").not( $(this).find(".folderIcon") ) //...
Or a slightly shorter version setting a context for the selector:
$(".folderIcon").not( $(".folderIcon", this) ) //...
$('.profileRowHeader').click(function () {
// reset state of all icons back to closed
$('.glyphicon').removeClass('glyphicon-folder-open').addClass('glyphicon-folder-close');
$('.glyphicon').find(':first').toggleClass('glyphicon-folder-close glyphicon-folder-open');
});

Categories