How to reset a CSS attribute that's been changed using JavaScript? - javascript

I have navigation buttons that increase in width from 100px, to 150px when hovered over :
nav li:hover{
width:150px;
}
But using javascript I have made it so that which ever option has been selected, will continue to have a width of 150px. When each option is selected, it makes the other options go back to 100px as I intended :
function show1(){
document.getElementById("nav1").style.width="150px";
document.getElementById("nav2").style.width="100px";
document.getElementById("nav3").style.width="100px";
}
function show2(){
document.getElementById("nav2").style.width="150px";
document.getElementById("nav1").style.width="100px";
document.getElementById("nav3").style.width="100px";
}
function show3(){
document.getElementById("nav3").style.width="150px";
document.getElementById("nav1").style.width="100px";
document.getElementById("nav2").style.width="100px";
}
The problem is, once one of the navigation options has been selected, they no longer increase in width to 150px when hovered over, because the functions have set them to stay at 100px.
I am trying to work out how to make it so that each of the navigation buttons always increases in width when hovered over, while whichever one has been selected stays at the increased length. So i'm trying to find a way to reset the width value to how it is defined by my CSS after each function is executed.
Anyone know how to solve this? I'm fairly beginner level at javacript.

I would do this by putting the "selected" style in a separate CSS class, and dynamically adding that class to the objects you want to have the fixed width, then dynamically removing it.
Fiddling with CSS classes in JS is not very difficult; see here for example.

Make it an empty string and it takes over the one from your stylesheet again
document.getElementById("nav2").style.width = "";

You should make use of classes and forget about modifying styles using javascript, you can see how inconvenient it is. Consider this example and how it simplifies everything:
CSS:
nav li:hover,
nav li.selected {
width: 150px;
background: coral;
}
and JS:
var selected = document.getElementsByClassName('selected');
function show(obj) {
if (selected.length) selected[0].className = '';
obj.className = "selected";
}
Here we go. Instead of three duplicated functions showX you now have only one.
Demo: http://jsfiddle.net/zGfLP/
It can be further improved if you move get rid of the onclick handlers from HTML:
var nav = document.getElementById('nav'),
selected = nav.getElementsByClassName('selected');
nav.onclick = function(e) {
if (e.target.nodeName === 'LI') {
if (selected.length) selected[0].className = '';
e.target.className = "selected";
}
};
Demo: http://jsfiddle.net/zGfLP/1/

Related

Weird behavior CSS overflow-y

I'm making a scrolling menu that has a list of cards, Each card has a button that shows more information.
the problem is that the overflow-y property hides the (toggled info) that should appear at the left side of the menu.
enter image description here
as you can see in the picture, I wanna get the (overflow-x visible) for the card-list but making it overflow-y: auto/scroll simply hide it
code Sandbox if you wanna take a look at the code:
https://codesandbox.io/s/github/Machfar-Souhayel/TestingOverflowBehavior
You could have the expanded version outside of the original list and just alter it to fit the item and then make it visible.
It also is not nessesary to create a class that make it visible/invisible and add and remove that with toggledElement.classList.add("show");
Instead just use element.style.display = 'block'; // 'none';
That way you do not need to use the target.children property but can call the function with an argument.
<button onclick="toggleClass('Title','Content');">Expand</button>
<script>
function toggleClass(header, content){
document.getElementsByClassName('expanded')[0].innerHtml = `<h1>${header}</h1><br><p>${content}</p>`;
document.getElementsByClassName('expanded')[0].style.display = 'block';
}
</script>
<style>
.expanded{
position: abolute;
top: 50vh;
left: 50vw;
transform: translate(-50%,-50);//just for some styling
display: none;
}
</style>
<div class="expanded"></div>
I hope I could help you.

Scroll both columns as one

My app has two columns, left side being a textarea, while the right side is the result calculated from the text area. But my result column would overflow the fixed window, while textarea would scroll by default.
So I've tried to set both the whole row and its parent to overflow: auto, which let me scroll when I've got enough input, but at the expense of having my separator not full height as well as having a delay after I've wrote into my textarea, before the dix snaps into a bigger height...
My final solution was to use JS & Jquery to check when content is overflown, to alternate between height: auto when it is and height: 100% when its not. That also kinda worked, but with wonky delays yet again...
const editor_js = document.querySelector('.editor');
const $editor = $('.editor');
$('.input').bind('input propertychange', function() {
console.log('Textarea changed');
if(editor_js.offsetHeight < editor_js.scrollHeight){
$editor.css("height", "auto");
}
else{
$editor.css("height", "100%");
}
});
Anyways I am at my wits end. I just want to have my columns consistently scrollable as one entity, while keeping the separator full height at all times. Hope you can give me some suggestions. If you want to directly do some attempts at my app, here's the link
The simplest way for you to get that effect would be to add that vertical border as a pseudo element on the parent. When I say simple, I mean it would be easy to set it and forget it. CSS would deal with it and it would be independant of the size
I think your best option will be to calculate the height of your text area in javascript and set the css style to it.
Then, Make sure you have the following css:
textarea.col-9.input {
overflow: hidden !important;
}
.main-body .editor {
overflow: scroll !important;
}
.col-lg-5.col-md-7.col-sm-8.main-body {
overflow: hidden;
}
I've tried it in Chrome's developer tools and it works well.

Add padding-top to scroll when using href="#id"

I have an anchor tag as follows:
A Guide
It navigates to a section that has the id 'map_4D85448A3D4C4180A02BD6FC387ABC45'. The jumptosection function is as follows:
function jumptosection(id) {
var target = document.getElementById(id);
if(document.all){
document.documentElement.scrollTop = target.offsetTop;
}else{
var top = 0;
do {
top += target.offsetTop || 0;
target = target.offsetParent;
} while(target);
document.body.scrollTop = top ;
}
//$('#article').css.paddingTop = '55px';
return false;
But even if I write nothing in this function, the behaviour is still the same. The problem is that I have a header strip of 92px that hides some part of the section when I click on the given anchor. How do I make it scroll to the given section while adding some pixels to escape the header?
While the chosen answer serves the purpose, we now have explicit CSS property for this, called scroll-margin.
Basically, you avoid any trickery by adding unnecessary elements - this margin is just calculated when you navigate via anchor tag (or if you have set up native css scroll snapping - https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap/Basic_concepts).
Using this with CSS variables is really useful. Here's an example if you have a fixed / sticky header:
/* Set the header variable */
--h-header: 50px;
/* Set the scroll margin top on all anchor elements by using .anchor class */
/* Note: I'm setting plus 2.5em so the element has some breathing room on the top */
.anchor {
scroll-margin-top: calc(var(--h-header) + 2.5em);
}
MDN Docs: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin
CSS-Tricks guide: https://css-tricks.com/almanac/properties/s/scroll-margin/
It is possible. I would do it without javascript, so it works for all. Even no changes on you JS are needed.
You just need to create an empty element above the element you want to scroll to. The CSS does the magic. It creates a hidden box in the height of you offset:
HTML:
<span class="anchor" id="map_4D85448A3D4C4180A02BD6FC387ABC45"></span>
<h1>Element to scroll to</h1>
CSS:
.anchor {
display: block;
height: 92px;
margin-top: -92px;
visibility: hidden;
}
See a working demo here:
https://jsfiddle.net/eczxm1rs/1/

Jquery manipulating Objects that currently have a classtag instead of manipulating the class itself?

So i am currently working on a responsive joomlatemplate, which will replace the navigation bar with a slide navigation as soon as the viewport gets to small. And as in this case I want to keep the navigation bar as long as possible, I proceeded as follows: I created two different css-classes for the navigation and I always assign the one needed via JS. I called those classes "portrait" and "landscape".
So in the css for portrait i got:
.portrait .menu li{
width = 100%;
...
}
And in the css for landscape i got:
.lanscape .menu li{
width = auto;
margin-left = 5px;
margin-right = 5px;
...
}
So now i determine the minimum width the navigation has to have in the js-file like this:
var minnavwidth = 0;
var navelements = $jQ("#main-navigation").find(".menu").children();
for (var i = 0; i < navelements.length; i++) {
minnavwidth += $jQ(navelements[i]).outerWidth(true);
}
But as i want the menuitems in the navigationbar evenly spread out i wrote this in a method that is only fired once:
$jQ(".landscape .menu li").css("width", 100 / navelements.length + "%");
The problem I have now is, that even after assigning the "portrait"-class to my navigation and also removing the "landscape"-class, the menuitems in the slidemenu still have a 20% width (5 menuitems atm). The only reason i can imagine is, that JQuery assigns the css to the DOMnodes that currently have a class instead of assigning it to the class itself. Is that correct? Is there any way around it other than reassigning the attributes manually every time i am switching classes?

Toggle background image of a link for accordion

I'm trying to get a links background image to toggle or swap on click for an FAQ accordion expand/contractable div using javascript.
I've gotten things working based on this jsfiddle example (http://jsfiddle.net/QwELf/)
You can see my page working here (http://bit.ly/1hfgcGL)
The problem comes in when you click one of the toggle links a 3rd time. It gets the wrong background image and is then out of sync with how it should look.
Right arrow > for contracted state and downward arrow for expanded state are how they should be but the opposite shows up.
It seems to work just fine in the jsfiddle on the 3rd or more clicks any idea what's going wrong with mine?
Script
<script type="text/javascript">
function changeArrow(element){
var arrow = element;
if(arrow.className == 'background_one'){
arrow.className = 'background_two';
} else {
arrow.className = 'background_one';
}
}
</script>
CSS
.background_one { text-decoration: none; padding-left: 26px; background: url(http://skmgroupwork.com/suntrust/landingpages/307m/chevright.gif) center left no-repeat;}
.background_two { text-decoration: none; padding-left: 26px; background: url(http://skmgroupwork.com/suntrust/landingpages/307m/chevdown.gif) center left no-repeat;}
HTML
<a class="background_one" data-toggle="collapse" data-target="#demo4" onClick="changeArrow(this)">If I transfer my balance to a new Access 3 Equity Line, what will my interest rate be?</a>
You need to check if it has class, not if it is, as you have several on times. As you use jQuery you can use .hasClass(), .addClass() and removeCLass(). You might also want to look at .toggleClass().
function changeArrow(element) {
var $arrow = $(element);
if ($arrow.hasClass('background_one')) {
$arrow.removeClass('background_one');
$arrow.addClass('background_two');
} else {
$arrow.removeClass('background_two');
$arrow.addClass('background_one');
}
}
That is happening because the className also contains the class collapsed the second time it's clicked.
I used IE's debugger and found this:
Perhaps you could use contains instead of equals, like the following (untested, but should work):
function changeArrow(element){
element.className = (arrow.className.contains('background_one') ?
'background_two' :
'background_one');
}

Categories

Resources