Toggling iron-collapse using javascript - javascript

I'm using multiple <iron-collapse>s with different IDs, and I have a <paper-icon-button> associated with each <iron collapse>.
I can use the <iron-collapse>s with their associated button when the screen is wider than 650px, but in narrower widths, why does clicking the <paper-icon-button> not toggle the <iron-collapse>?
I even tried to change the class of a particular <iron-collapse>, but no luck. Toggling the display property didn't help.
Here's the template:
<paper-icon-button
class="pull-left"
id$="generalSectionToggle##[[yearEntries]]-[[monthEntries]]"
icon="expand-less"
on-click="toggleGeneralSection">
</paper-icon-button>
<iron-collapse id$="generalSection-[[yearEntries]]-[[monthEntries]]" opened="true">
<div class="container-vertical">
Some Content
</div>
</iron-collapse>
Here's the on-click handler (toggleGeneralSection):
var elementID = event.target.parentElement.id.split("##")[1]
var element = "generalSection-" + elementID
var domElement = document.getElementById(element);
if (window.innerWidth > 650) {
domElement.toggle();
} else {
if (domElement.opened) {
domElement.classList.toggle('iron-collapse-closed');
} else {
domElement.classList.toggle('iron-collapse-opened');
}
}
if (domElement.opened) {
event.target.icon = "expand-less";
} else {
event.target.icon = "expand-more";
}

The iron-collapse doesn't toggle when the window is less than 650px because you're not calling <iron-collapse>.toggle() in that scenario. Instead, you're toggling an internal class. It seems the intention is to always toggle regardless of the screen width, so you should always call <iron-collapse>.toggle().
Also, you should avoid using document.getElementById() in your click-handler to fetch the <iron-collapse> because it won't work in Shadow DOM. Instead, you could use this.$$(selector). In your case, you're querying for an element ID, so you should prefix element with # (i.e., "#generalSection-" + elementID).
Your code should look more like this:
var elementID = event.target.parentElement.id.split("##")[1]
var element = "#generalSection-" + elementID
var domElement = this.$$(element);
domElement.toggle();
if (domElement.opened) {
event.target.icon = "expand-less";
} else {
event.target.icon = "expand-more";
}
See this codepen demo that toggles the <iron-collapse> with <paper-icon-button> and uses a computed binding for the icon. And see this codepen for a variation that makes the header a clickable toggle.

Related

How can I hide a div that I've just added with a click?

I'm appending some HTML to my button on a click, like this:
jQuery(document).ready(function($) {
$('#sprout-view-grant-access-button').on('click', function(e) {
$(this).toggleClass('request-help-cta-transition', 1000, 'easeOutSine');
var callback = $(e.currentTarget).attr('data-grant-access-callback');
var wrapper = $('.dynamic-container');
console.log(wrapper);
if( typeof window[callback] !== 'function') {
console.log('Callback not exist: %s', callback);
}
var already_exists = wrapper.find('.main-grant-access');
console.log(already_exists);
if( already_exists.length ) {
already_exists.remove();
}
var markup = $(window[callback](e.currentTarget));
wrapper.append(markup);
});
});
function generate_grant_access_container_markup() {
var contact_data_array = contact_data;
var template = jQuery('#template-sprout-grant-access-container')
return mustache(template.html(), {
test: 's'
});
}
As per the code, whatever comes from generate_grant_access_container_markup will be put inside dynamic-container and shown.
My problem is that, the newly added code just doesn't wanna dissapear upon clicking (toggle) of the button once again.
Here's my syntax / mustache template:
<script type="template/mustache" id="template-sprout-grant-access-container">
<p class="main-grant-access">{{{test}}}</p>
</script>
And here's the container:
<div class="button-nice request-help-cta" id="sprout-view-grant-access-button" data-grant-access-callback="generate_grant_access_container_markup">
Grant Devs Access
<div class="dynamic-container"></div>
</div>
I understand that the click event only knows about items that are in the DOM at the moment of the click, but how can I make it aware of everything that gets added after?
I would recommend visibility: hidden. Both display none and removing elements from the dom mess with the flow of the website. You can be sure you would not affect the design with visibility: hidden.
I don't deal with Jquery at all but it seems like this Stack overflow covers the method to set it up well.
Equivalent of jQuery .hide() to set visibility: hidden

Change styling of a psuedo after element with javascript

Is it possible to change the styling of a psuedo :after element with javascript something like this:
document.querySelector('#test:after').attr("style", "content:url('blabla.png')");
Is there any workaround to change the image after 1 click like this:
var timesClicked = 0;
span = document.querySelector('.socialShare');
span.addEventListener('click', function (e) {
timesClicked++;
if (timesClicked > 1) {
document.querySelector('#socialShare').style.left = '-60px';
timesClicked = 0;
console.log(timesClicked)
} else {
document.querySelector('#socialShare').style.left = '0';
document.querySelector('#socialShare:after').attr("style", "content:url('blabla.png')");
console.log(timesClicked)
}
});
Or maybe better transform the image it is about an arrow which needs to point the other way when div is expanded
You can't change styles of pseudo elements with javascript, because they are not part of the DOM, and so do not have any API to work with.
Usual approach is to change classes of the element itself and have those classes affect related pseudo elements. For example in your case:
// Add class selected to element
document.querySelector('#test').classList.add('selected')
In CSS:
#test.selected::after {
content: url('blabla.png');
}

Remove Class when current toggle is clicked

The title is a bit of a tongue twister. A brief description of the fiddle, is that it's a toggle style accordion where the toggle state changes color when one of the divs is toggled. I've got it working to where if another div is toggled it will close that previous div and open the new div while changing the toggle state.
The issue I am running into is if a user wants to close the current toggle without clicking a different div it will close the current toggle but not change the toggle state back to it's original state. I am currently using this and have tried multiple things including if the container 'is: visible' or hasClass then to remove the toggle class, but nothing seems to work. I've also tried a different slideToggle function, but of course that applied it to the toggled element I've found.
Fiddle: http://jsfiddle.net/NFTFw/1256/
What I am trying to do?
I want the current toggle class to change back to its original state if the user clicks the current toggled div or clicks another div. So essentially I want the user to have either option.
CODE:
$(document).ready(function () {
$('.column').each(function (index) {
$(this).delay(750 * index).fadeIn(1500);
});
$('.column').hide();
$('.body').hide();
$('.column').each(function () {
var $toggle = $(this);
$('.toggle', $toggle).click(function () {
$(".toggle").removeClass("toggle-d");
$(this).addClass('toggle-d');
$body = $('.body', $toggle);
$body.slideToggle();
$('.body').not($body).hide();
});
});
});
Check to see if the thing that you're clicking already has the class. If so, remove it, if not, add it. I suspect the problem you were having with hasClass() is that you were attempting to check the wrong this.
Oooh I did a bad thing and didn't remove the class when a new div was clicked. I've fixed that and updated the jsfiddle
jsfiddle
js:
$(document).ready(function () {
$('.column').each(function (index) {
$(this).delay(750 * index).fadeIn(1500);
});
$('.column').hide();
var width = $(window).width();
if (width <= 600) {
$('.body').hide();
$('.column').each(function () {
var $toggle = $(this);
$('.toggle', $toggle).click(function () {
if($(this).hasClass('toggle-d')){
$(this).removeClass("toggle-d");
}
else{
$('.toggle').removeClass('toggle-d');
$(this).addClass('toggle-d');
}
$body = $('.body', $toggle);
$body.slideToggle();
$('.body').not($body).hide();
});
});
}
});
What i would suggest is to pass the element itself in the function
in the index.html Do this
<a class = 'classname' onclick = toggle(this)>
Your Content Here
</a>
After that in the script.js
what i am saying is in javascript, i believe you can easily convert it to jquery
function toggle(value){
if(value.className == 'the predefined value'){
value.className = value.className + ' Your new class addition'
// remember there should be a space if you are adding an additional class to the present class, else directly change the classname
}
else{
value.className = 'the predefined value'
}}
this will toggle your classname whenever the element is clicked

How do I change the CSS property "display" in javascript

How do I change the CSS property display, in JavaScript, from display:none to display:normal for these divs?
#hide_0 { display:none }
#hide_1 { display:none }
#hide_2 { display:none }
#hide_3 { display:none }
#hide_4 { display:none }
#hide_5 { display:none }
Only one at a time. I need to display one and hide the rest.
What I used:
var persistent_element='hide_1';
function link_update(link_display)
{
var local_element;
local_element=document.getElementById(persistent_element);
local_element.style.display='none';
local_element=document.getElementById(link_display);
local_element.style.display='block';
persistent_element=link_display;
}
How I connected it : m4 is a minified - connects onclick to these methods
m4('l1',function {return link_update(hide_1);});
m4('l2',function {return link_update(hide_2);});
m4('l3',function {return link_update(hide_3);});
m4('l4',function {return link_update(hide_4);});
m4('l5',function {return link_update(hide_5);});
m4('l6',function {return link_update(hide_6);});
To use javascript to change the style, you can do it like this:
// hide an element
document.getElementById("hide_0").style.display = "none";
// show a block element
document.getElementById("hide_1").style.display = "block";
// to go back to the default or CSS specified value
document.getElementById("hide_2").style.display = "";
So, if you wanted to hide all and show one, you could do that with this function:
function showOneHideOthers(base, len, numToShow) {
// objects must have ids like base_0, base_1, etc...
for (var i = 0; i < len; i++) {
if (i != numToShow) {
document.getElementById(base+i).style.display = "none";
}
}
document.getElementById(base+numToShow).style.display = "block";
}
showOneHideOther("hide_", 6, 2);
P.S. normal is not a valid value for the display property. The typical values are block, none and inline and there are others like inline-block, table, etc....
Your question is not particularly clear, but the essence of what you want to do is simple. You can get a reference to a DOM element which has an id using getElementById, and you can change the display property:
document.getElementById("hide_0").style.display = "none"; //or "block"
However, you have several element that you want to hide/show (I'm not sure when you want to do so), so it may be easier to use a different method of selecting the elements (such as getElementsByTagName, or getElementsByClassName, but it depends on your HTML and what you're actually trying to do).
You can set a css property on an element using the style method.
div.style.display = '';

CSS: Suppressing negative margins of child elements

I have a parent element (e.g. a div) which surrounds some dynamic content. I would like the parent div to fully contain the child elements in as many circumstances as possible.
One problem is child elements with negative margin settings, which cause the child element to be displayed outside of the parent element (and also cause the parent element not to be of the desired size).
So
Is there any css trick that can be applied to the parent in order to suppress the negative margins in the child elements (e.g. without having to modify the styles on the child).
Failing that, is there anyway to detect via javascript whether a particular element has overflowing content? (and in which direction and to what degree the content is overflowing?)
Did you try to put a class to the parent like:
.parentDiv > * {
margin:0 !important;
}
To have the parent with the desired height, you need to set some css too:
.parentDiv{
overflow:hidden;
position:relative;
background:#DFE;
padding:5px;
}
There is a javascript method of handling this, but it's certainly not as clean as #Mic's CSS solution. I haven't completely tested this, and you may need to add some support for various padding/margin adjustments, but it would get somebody started if a JS-solution was the only option. Using prototype.js (jquery would be similar, but plain javascript will be very.. stretchy):
function checkOverflow (child) {
child = $(child);
if (child.descendants().any()) {
child.getElementsBySelector("> *").each(function(e) {
checkOverflow(e);
});
}
var parent = child.up();
var child_left = child.cumulativeOffset()['left'], child_top = child.cumulativeOffset()['top'];
var child_height = child.getDimensions()['height'], child_width = child.getDimensions()['width'];
var parent_left = parent.cumulativeOffset()['left'], parent_top = parent.cumulativeOffset()['top'];
var parent_height = parent.getDimensions()['height'], parent_width = parent.getDimensions()['width'];
if (child_top < parent_top) {
if (child_left < parent_left) {
// adjust element style here
} else if (child_left > parent_left + parent_width) {
// adjust element style here
}
} else if (child_top > parent_top + parent_height) {
if (child_left < parent_left) {
// adjust element style here
} else if (child_left > parent_left + parent_width) {
// adjust element style here
}
}
}
My general feeling, though, is that you should only do this if it can't be explicitly done through CSS.

Categories