Toggle code not working in IE11 - javascript

Here is my code for a class called Toggle, that toggles multiple components in my site. The HTML has a data attribute on it called data-expand-content, and the css is set up to say that when data-expand-content is true, display: block or whatever this content. And the JS is what toggles the data attribute on click. It works fine on all browsers except for IE11, please help me figure out what is wrong?
Thanks!
Here's the JS
class Toggle {
constructor(control, el) {
const toggleLink = document.querySelector('.primary-nav__toggle-link');
control = document.querySelector(control);
el = document.querySelector(el);
if(el) {
control.addEventListener('click', function(e) {
if(el.dataset.expandContent == "false") {
el.dataset.expandContent = "true"
if(e.target == document.querySelector('.primary-nav__toggle-icon')) {
document.querySelector('.primary-nav__toggle-icon').setAttribute('src', '../assets/close-menu.svg');
}
} else {
el.dataset.expandContent = "false";
if(e.target == document.querySelector('.primary-nav__toggle-icon')) {
document.querySelector('.primary-nav__toggle-icon').setAttribute('src', '../assets/burger-menu.svg');
}
}
})
}
}
}
// new instances of class that get passed a control and a the element that gets toggled
const menu = new Toggle('.primary-nav__toggle-link', '#primary-nav');
const bannerEl = new Toggle('.banner', '.banner');

Related

How to trigger a function on parent div when iframe content is clicked?

I'm trying to create a reusable function that works by hiding a specific div (outside the iframe) whenever a click is made anywhere inside an iframe.
To be more specific, this div I want to hide is a search menu that can be opened on top (z-index) of an iframe. I'd like to close this menu whenever I click outside it, which happens to be inside the full screen iframe.
I couldn't make it work using the solutions from this and other similar pages (Whenever I change the URL, it doesn't work anymore): Detect click event inside iframe
I managed to do something like this that works but the code is repetitive. I'd like a more general function that works whenever I click inside any iframe.
const iframeListener1 = addEventListener('blur', function() {
if (document.activeElement === document.getElementById('chrono-loader')) {
$('#outer-layer-card').stop().fadeOut('fast');
}
removeEventListener('blur', iframeListener);
});
const iframeListener2 = addEventListener('blur', function() {
if (document.activeElement === document.getElementById('plus-loader')) {
$('#outer-layer-card').stop().fadeOut('fast');
}
removeEventListener('blur', iframeListener);
});
const iframeListener3 = addEventListener('blur', function() {
if (document.activeElement === document.getElementById('google-docs-1-loader')) {
$('#outer-layer-card').stop().fadeOut('fast');
}
removeEventListener('blur', iframeListener);
});
const iframeListener4 = addEventListener('blur', function() {
if (document.activeElement === document.getElementById('google-sheets-2-loader')) {
$('#outer-layer-card').stop().fadeOut('fast');
}
removeEventListener('blur', iframeListener);
});
const iframeListener5 = addEventListener('blur', function() {
if (document.activeElement === document.getElementById('google-docs-3-loader')) {
$('#outer-layer-card').stop().fadeOut('fast');
}
removeEventListener('blur', iframeListener);
});
const iframeListener6 = addEventListener('blur', function() {
if (document.activeElement === document.getElementById('google-docs-4-loader')) {
$('#outer-layer-card').stop().fadeOut('fast');
}
removeEventListener('blur', iframeListener);
});
How can I trigger a function (to hide one specific div) whenever I click on any iframe?
Thanks in advance for any suggestions or help
Can save event listeners into a object and have a function to add them dynamically. That would mean to have some sort of html element which would have data-target attribute or similar. Additionaly can move the id_target to function parameter.
var iframe_listeners = [];
function add_iframe_event(){
const id_target = $('data-target element').data('target');
iframe_listeners[id_target] = addEventListener('blur', function() {
if (document.activeElement === document.getElementById(id_target)) {
$('#outer-layer-card').stop().fadeOut('fast');
}
removeEventListener('blur', iframe_listeners[id_target]);
});
}
Edit:
loop method
var iframe_listeners = [];
const ids = [ '1', '2' ];
for(const id of ids){
// skip if element doesnt exist
if($(`#${id}`).length == 0) continue;
add_iframe_event(id);
}
function add_iframe_event(id_target){
iframe_listeners[id_target] = addEventListener('blur', function() {
if (document.activeElement === document.getElementById(id_target)) {
$('#outer-layer-card').stop().fadeOut('fast');
}
removeEventListener('blur', iframe_listeners[id_target]);
});
}

How to run only one function if we have multiple class

So. to begin with,
I am writing my eventlisteners in this way.
document.addEventListener('click',(e)=>{
const element = e.target;
if(element.classList.contains('classOne'){
fire_function_one();
}
if(element.classList.contains('classTwo'){
fire_function_two();
}
});
I have a div like follows
<div class='classOne classTwo'>Something</div>
So what I want to achieve is,
When our div has classOne, I want to fire 'fire_function_one()', However when our div has both classOne and ClassTwo, I want to fire 'fire_function_two()' but I dont want to run 'fire_function_one()'.
What I have tried,
event.stopPropogation; //Not working
event.preventDefault; //Not working
if(element.classList.contains('classTwo' && !element.classList.contains('classOne'){
fire_function_two();
//Doesnt acheive what I want
}
Change the Order of your condition and use else if statement.
document.addEventListener('click',(e)=>{
const element = e.target;
if(element.classList.contains('classTwo'){
fire_function_two();
}
else if(element.classList.contains('classOne'){
fire_function_one();
}
});
If you are sure that the element can have classOne or both classTwo and classOne, you can just change the order and use else if statement:
document.addEventListener('click',(e)=>{
const element = e.target;
if(element.classList.contains('classTwo'){
fire_function_two();
} else if(element.classList.contains('classOne'){
fire_function_one();
}
});
You need to write click on element as below.
var eleOne = document.getElementsByClassName('classOne')
if(eleOne.length > 0) {
var currentEleOne = eleOne[0];
currentEleOne.onclick = function () {
// Click code for classOne
}
}
var eleTwo = document.getElementsByClassName('classTwo')
if(eleTwo.length > 0) {
var currentEleTwo = eleTwo[0];
currentEleTwo.onclick = function () {
// Click code for classTwo
}
}
Here you have two cases,
When both classes are present, fire only class two
If only class one is present, fire class one
So, First check with if whether both classes are present or not. If true then fire class two. Otherwise inside else if, check if class one is present and if this condition is met, fire class one.
document.addEventListener('click', function(e) {
const element = e.target;
if (element.classList.contains('classTwo')) {
console.log("Fire class two");
} else if (element.classList.contains('classOne')) {
console.log("Fire class one");
}
});
<div class='classOne classTwo'>Something 1 2</div>
<div class='classOne'>Something 1</div>
You could try a simple ternary like this:
document.addEventListener('click', (e) => {
const element = e.target;
element.classList.contains('classTwo') ? fire_function_two() : fire_function_one();
});
If the classList contains 'classTwo' then run fire_function_two() else fire_function_one()

javascript that hides/shows element based on criteria not working with style.display = "none"

I have this section of javascript in my html that grabs a form input, puts it through a function and returns a json. I then want to either hide or show certain form elements based on the values in this json.
At the moment, i can do all of this fine except for changing the style.display properties of the elements im trying to hide/show, i can find them okay with getElementbyId (have tested this with other stuff) but the changes i make to the style don't seem to do anything.
As you can see below, i have put in a few alerts to make sure everything is working, and they all seem to align with what i need from the function. The alert showing style.display even matches up with what i'm trying to change it to, however even if it says "none", the form element still shows up.
<script type="text/javascript">
let selected = document.getElementById('selection1');
let optional_toggle = document.getElementById("optional_element");
let button = document.getElementById("button")
button.onclick = function() {
choice1 = selected.value;
fetch('/form_choice/' + choice1).then(function(response) {
response.json().then(function(data) {
if (data.show_optional === "True") {
optional_toggle.style.display = ""
window.alert("first part of if");
window.alert(optional_toggle.style.display);
window.alert(data.show_optional);
}
else {
optional_toggle.style.display = "none"
window.alert("second part of if");
window.alert(optional_toggle.style.display);
window.alert(data.show_optional);
console.log(optional_toggle);
}
}
)
}
)
}
</script>
Edit: i added the console.log lines in but nothing seems to show in the console.
console log image
The issue was that the page was reloading to it's original state after the script had been executed, so i stopped this by adding "; return false" after the function like so:
<script type="text/javascript">
let selected = document.getElementById('selection1');
let optional_toggle = document.getElementById("optional_element");
let button = document.getElementById("button")
button.onclick = function() {
choice1 = selected.value;
fetch('/form_choice/' + choice1).then(function(response) {
response.json().then(function(data) {
if (data.show_optional === "True") {
optional_toggle.style.display = ""
window.alert("first part of if");
window.alert(optional_toggle.style.display);
window.alert(data.show_optional);
}
else {
optional_toggle.style.display = "none"
window.alert("second part of if");
window.alert(optional_toggle.style.display);
window.alert(data.show_optional);
console.log(optional_toggle);
}
}
)
}
); return false
}
</script>

How do I get my modal to close when a user clicks on the container?

I'm currently studying a full stack course and my modal isn't behaving as expected
I'm a bit lost on what to do as I can't find any documentation anywhere and while clicking on the close button or pressing ESC works, clicking outside of the box doesn't.
The following code is how it has been suggested I approach the issue but, it doesn't work. I've honestly stared at this for about an hour and just can't connect the dots on what is (not) happening? Please excuse all the commenting and additional code as I'm still learning so, it's how I'm able to follow what's going on:
function showModal() {
var $modalContainer = document.querySelector('#modal-container');
$modalContainer.classList.add('is-visible');
}
function hideModal() {
var $modalContainer = document.querySelector('#modal-container');
$modalContainer.classList.remove('is-visible');
}
//modal IFFE
document.querySelector('#modal-button').addEventListener('click', () => {
showModal();
});
//-- show modal --
function showModal(title, text) {
var $modalContainer = document.querySelector('#modal-container');
//Selects the element with the associated id
// Clear all content for the selected element
$modalContainer.innerHTML = '';
var modal = document.createElement('div'); //creates a div element withing selected element
modal.classList.add('modal'); //assigns new class to the div element
// Add the new modal content
var closeButtonElement = document.createElement('button'); //creates the close button
closeButtonElement.classList.add('modal-close'); //assigns a class to the new (close) button
closeButtonElement.innerHTML = "×"; //inserts text within the new(close) button
closeButtonElement.addEventListener('click', hideModal);
var titleElement = document.createElement('h1');
titleElement.innerText = title;
var contentElement = document.createElement('p');
contentElement.innerText = text;
modal.appendChild(closeButtonElement);
modal.appendChild(titleElement);
modal.appendChild(contentElement);
$modalContainer.appendChild(modal);
$modalContainer.classList.add('is-visible');
}
document.querySelector('#modal-button').addEventListener('click', () => {
showModal('PokéMon', 'Here is all of the info about your PokéMon');
});
window.addEventListener('keydown', (e) => {
var $modalContainer = document.querySelector('#modal-container');
if (e.key === 'Escape' && $modalContainer.classList.contains('is-
visible')) {
hideModal();
}
});
$modalContainer.addEventListener('click', (e) => {
var target = e.target;
if (target === $modalContainer) {
hideModal();
}
});
Expected result: User clicks outside of the modal (on the container) and the modal closed.
Current result: No change in state, modal remains active and visible. Only by clicking on the close button (x) or by pressing ESC is the desired result achievable.
By Looking at this code I am not sure what is actually supposed to make the modal visible or hide it. Without access to your css (if you have any). I am assuming that all you are doing is adding and removing the class .is-visible from the #modal-container element.
I would suggest that you apply this class to the modal itself, and then you could toggle this class on and off,
Modify your code to do this by doing something like this (added on top of your code):
function showModal() {
var $modalContainer = document.querySelector('#modal-container');
$modalContainer.classList.add('is-visible');
document.querySelector('.modal').classList.remove('hide-el')
}
function hideModal() {
var $modalContainer = document.querySelector('#modal-container');
$modalContainer.classList.remove('is-visible');
document.querySelector('.modal').classList.add('hide-el')
}
Where hide-el in your css is:
.hide-el {
display: none;
}
You could also modify your code to appply the is-visible class to your modal element. You should always try to attach the class/id to the element you want to manipulate if you have that option.
Or if you do not have access to a css file:
document.querySelector('.modal').style.display = "none"
and
document.querySelector('.modal').style.display = "block"
Also, your code seems very verbose, was this boilerplate part of the assignment?
heres a working example: https://codepen.io/mujakovic/pen/zVJRKG
The code was in the incorrect place in the end and should have looked something like this:
modal.appendChild(closeButtonElement);
modal.appendChild(titleElement);
modal.appendChild(contentImage);
modal.appendChild(contentHeight);
modal.appendChild(contentElement);
$modalContainer.appendChild(modal);
$modalContainer.classList.add('is-visible');
$modalContainer.addEventListener('click', (e) => { //listening for an event (click) anywhere on the modalContainer
var target = e.target;
console.log(e.target)
if (target === $modalContainer) {
hideModal();
}
});
};
window.addEventListener('keydown', (e) => { //listening for an event (ESC) of the browser window
var $modalContainer = document.querySelector('#modal-container');
if (e.key === 'Escape' && $modalContainer.classList.contains('is-visible')) {
hideModal();
}
});
This is because the action was originally being called on page load and targeted within the window instead of being called within the container and being loaded when the modal loads.
Thank for your help

(Javascript) Div toggle and cookies

I want to toggle a div#featuredout using a button .featToggle and I want the browser to remember via cookies whether the div#featuredout should be hidden or shown. If possible, I'd like it to be so that if #featuredout is hidden, .featToggle should have an additional class of "hidden" and if #featuredout is shown, .featToggle should have an additional class of "shown".
I'm very very inexperienced with Javascript so any help would be great.
This is my current code:
$(document).ready(function() {
// When the toggle button is clicked:
$('.featToggle').click(function() {
$('#featuredout').slideToggle(550);
var featuredoutC = $.cookie('featuredout');
if (featuredoutC == null) {$.cookie('featuredout', 'expanded');};
else if (featuredoutC == 'expanded') {$.cookie('featuredout', 'collapsed');};
});
});
// COOKIES
// state
var featuredout = $.cookie('featuredout');
// Set the user's selection for the left column
if (featuredout == 'collapsed') {
$('#featuredout').css("display","none");
$.cookie('featuredout', 'collapsed');
};
});
Something along the lines of this should work
$(function() {
$('.featToggle').click( function() {
$('#featuredout').slideToggle(550);
$.cookie('featuredout',$('#featuredout').is(':visible'););
});
var vis = $.cookie('featuredout');
if(vis) {
$('.featToggle').removeClass('hidden').addClass('shown');
} else {
$('#featuredout').hide();
$('.featToggle').removeClass('shown').addClass('hidden');
}
});

Categories

Resources