Button does not respond to DOM cssStyleDeclaration - javascript

I am sure this is a simple bug but I´ve been over an hour trying to find where the problem is and definetely could use a different point of view.
In the following function I change the style of two buttons. One of them, responds correctly and indeed its font size changes when the function gets called (deleteBtnToDecorate).
The other one, I cant understand why it doesn´t responds and it´s font size doesn´t get changed (doneBtnToDecorate):
changeStyle: function(idNumber){
const liToDecorate = document.getElementById(`id${idNumber}`)
const doneBtnToDecorate = document.getElementById(`idDone${idNumber}`)
const deleteBtnToDecorate = document.getElementById(`idDelete${idNumber}`)
liToDecorate.style.textDecoration = 'line-through'
doneBtnToDecorate.style.fontSize = '0.8rem'
deleteBtnToDecorate.style.fontSize = '1.1rem'
}
Things I´ve tried:
console logged clicking in both buttons to verify all of them are
targeted correctly. They are
changed css font size manually to verify in case bootstrap might be
the problem (although if it would be, the other button wouldn´t
change either) but anyway...the fact is: It changes succesfully
when i do it via CSS and not the DOM
This is my full code:
<ul class="item-list-ul">
<li
v-for="(i, index) in items"
:id="`id${index}`"
:key="index">{{ i }}
<div class="item-butons">
<b-button :id="`idDone${index}`" class="done-btn" #click="changeStyle(index)" size="sm" variant="outline-dark">Hecho!</b-button>
<b-button :id="`idDelete${index}`" class="delete-btn" #click="deleteItem(i)" size="sm" variant="warning">Borrar</b-button>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'TodoList',
methods: {
changeStyle: function(idNumber){
const liToDecorate = document.getElementById(`id${idNumber}`)
const doneBtnToDecorate = document.getElementById(`idDone${idNumber}`)
const deleteBtnToDecorate = document.getElementById(`idDelete${idNumber}`)
liToDecorate.style.textDecoration = 'line-through'
doneBtnToDecorate.style.fontSize = '0.8rem'
deleteBtnToDecorate.style.fontSize = '1.1rem'
}
}
}
</script>
<style lang="css">
.item-wrapper{
padding: 4vh 3vh 4vh 3vh;
}
.item-list-ul{
margin-right: 4vh;
}
.item-list-ul li{
margin-bottom: 3vh;
}
.item-list-ul li{
font-size: 1.4em !important;
font-weight: 600;
list-style: outside none none;
}
.done-btn{
margin-right: 20px;
font-size: 1rem !important;
font-weight: 600 !important;
}
.delete-btn{
font-size: 0.9rem;
font-weight: 600 !important;
}
</style>

Your CSS uses !important:
.done-btn {
...
font-size: 1rem !important;
...
}
If you use !important it will take precedence over inline styles.
Incidentally, this is not really the correct way to do this in Vue. You should apply the changes within the template via either class or style bindings rather than grabbing elements and changing them directly.

Related

Hide or remove child elements and characters by CSS stylesheet

I'm just having difficulty here figuring out how to hide child elements via CSS. I know it's easy doing by JS, but the Zendesk widget script is not allowing that. Well here's the code I have right now:
let style = document.createElement('style');
style.innerHTML = `
.eRhaXm {
text-align: center !important;
margin-left: 0px !important;
font-size: 0px !important;
},
`;
parent.document.getElementById('webWidget').contentWindow.document.head.appendChild(style);
BTW, the current style is on the iframe. And here is the element I want to hide:
<div aria-hidden="true" class="styles__Name-sc-1dpp62d-1 eRhaXm">
<span>Kopi Help</span> ·
<span>Bot</span>
</div>
I want to get rid of that . and the <span> element Bot. So it will only just remain:
<div aria-hidden="true" class="styles__Name-sc-1dpp62d-1 eRhaXm">
<span>Kopi Help</span>
</div>
Since the <span> you want to address does not have any class name, you will need to style elements based on the DOM structure. This might be problematic, because then your script is sensible to any change.
You also can use Descendent combinator to address children of an element, or the more specific Child combinator
.eRhaXm span:nth-of-type(2) { display: none; }
Unfortunately, text nodes are not visible to CSS. But, since it is text, you can hide it differently, for example by setting font-size to 0, which you already did.
.eRhaXm { font-size: 0 }
.eRhaXm * { font-size: 1rem }
After all, all this is quite hacky and will break once the source DOM changes.
Also, it has accessibility issues, for example the aria-hidden attribute is completely hiding this name element from assistive technologies.
.eRhaXm {
text-align: center !important;
margin-left: 0px !important;
font-size: 0px !important;
}
.eRhaXm * { font-size: 1rem }
.eRhaXm span:nth-of-type(2) { display: none }
<div aria-hidden="true" class="styles__Name-sc-1dpp62d-1 eRhaXm">
<span>Kopi Help</span> ·
<span>Bot</span>
</div>

Best way to change className in Next.js when a button is clicked, with CSS Modules?

I am creating a basic nav bar and I want to change it based on screen size. Once it hits 600px i'd like to hide the links and display a clickable nav button that will expand those options.
After console logging my list Elements I found that the className was given this 'Nav_floatLeft__H1YZ8'. So based on that finding, my code is as follows. However, my navigation does not display any changes when clicking the button.
I'm sure React has a better way of handling this situation, but I'm fairly new to it. Should I be using some kind of state/effect hook?
Nav:
const openCloseMenu = () => {
console.log(document.getElementsByClassName(styles.floatLeft).className);
let elements = document.getElementsByClassName(styles.floatLeft);
if (elements.className === "Nav_floatLeft__H1YZ8"){
alert("Changed to: Menu Bar Expanded");
elements.className = styles.menuBarExpanded;
}
else {
alert("Changed Back to: Float Left")
elements.className = styles.floatLeft;
}
}
return (
<div className={styles.topNav}>
<nav>
<ul className={styles.inlineListItem}>
<li className={styles.floatLeft}>
<Link href="/">
<a>Home</a>
</Link>
</li>
<li className={styles.floatLeft}>
<Link href="/search">
<a>Search</a>
</Link>
</li>
<li className={styles.menuBar}>
<button onClick={openCloseMenu}>Expand Nav</button>
</li>
</ul>
</nav>
</div>
)
CSS:
.inlineListItem{
display: inline;
list-style: none;
}
.floatLeft{
float: left;
margin: 1rem;
padding-left: 1rem;
text-align: center;
color: white;
}
.floatRight{
display: inline;
float: right;
color: white;
margin: 1rem;
padding-right: 2rem;
}
.menuBar{
display: none;
float: left;
margin: 1rem;
padding-left: 1rem;
text-align: center;
color: white;
}
.menuBarExpanded{
display: block;
}
#media screen and (max-width: 600px) {
.menuBar{
display: block;
}
.floatLeft{
display: none;
}
.floatRight{
display: none;
}
}
ways are there to solve this problem.
You can use material UI. To detect the breakpoint.
Like for you case. If want to detect 600px.
you can do something like that ---
const themeBreakpoint = theme.breakpoint.down('600px) // themeBreakpoint will be true under 600px.
using this flag you can change state and show what ever you want by using condition rendering.
Second Problem --
you can change any state based on onClick event.
like --
const[clicked,setclicked] = useState(false)
const handleClick = (e) =>{
setclicked(true)
}
now when you make that clicked flag true, You change you css class based on that flag.
You could implement an useState hook:
import { useState } from "react";
const YourComponent = () => {
const [cliked, setClicked] = useState(false);
return (
<YourNavbar className={clicked ? "display" : "hide"} />
....
<button onClick={() => setClicked(current => !current)}>Expand Nav</button>
....
)
}
And on css, you can establish the class display with the actual attributes of the navbar, and a hidden (display: none)
This will check if the navbar button has been clicked (set to true), and on the conditional class, if its true, then it will display the navbar through the "display" class, if the button is clicked again, clicked will be false and the class for the navbar will be "hidden".
Remember to delegate this classnames to the item only when the navbar is below 600px with #media

Using dark or light mode

what is the best way to incorporate something like this into my site? I've tried using plugins but I cant get it to work. Doesn't have to be fancy.
Does anyone have it or have used one in the past they can recommend? Otherwise, is there a way to code it using JavaScript?
You could just set a button to trigger a boolean for example and based on its values, change the background-color of the items you want to change into dark mode.
I personally used react context for this one, something like this (kinda perfect how they used theme as an example). You should study it.
It depends on your framework, but if you use Material-UI, it has this option.
you can change palette type from light to dark and vice versa to achieve your requirements. Take a look here.
But if you don't use any framework, you should make a css structure that has two classes, light and dark, have some properties like color and background color and etc., and when the toggle theme button clicked, you will change all your classes from light to dark for example, also you can use animation for the effects.
There is a multiple solutions for this problem, if you are using a specific framework I suggest you check if there a way to do it with it, if you are not using any framework you still have multiple solutions and I suggest to create for each element you want to change his properties to dark mode another CSS class for each one, and with JavaScript create a function (that can call by a button on the html) that change all the element you want to those external classes, and if you click this button once again is reverse the function and make all the classes be with the original CSS classes
Maybe this should help you to kickstart.
<html class="theme-light">
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
.theme-light {
--color-primary: #0060df;
--color-secondary: #fbfbfe;
--color-accent: #fd6f53;
--font-color: #000000;
}
.theme-dark {
--color-primary: #17ed90;
--color-secondary: #243133;
--color-accent: #12cdea;
--font-color: #ffffff;
}
.container {
display: flex;
width: 100%;
height: 100%;
background: var(--color-secondary);
flex-direction: column;
justify-content: center;
align-items: center;
}
.container h1 {
color: var(--font-color);
}
.container button {
color: var(--font-color);
background: var(--color-primary);
padding: 10px 20px;
border: 0;
border-radius: 5px;
}
</style>
<script>
// Set a Theme
function setTheme(themeName) {
localStorage.setItem('theme', themeName);
document.documentElement.className = themeName;
}
// Toggle From light and dark theme and Vice-Versa
function toggleTheme() {
if (localStorage.getItem('theme') === 'theme-dark') {
setTheme('theme-light');
} else {
setTheme('theme-dark');
}
}
// Onload Theme
(function() {
if (localStorage.getItem('theme') === 'theme-dark') {
setTheme('theme-dark');
} else {
setTheme('theme-light');
}
})();
</script>
<body>
<div class="container">
<h1>Theme Switcher</h1>
<button id="switch" onclick="toggleTheme()">Switch Theme</button>
</div>
</body>
</html>
This is a simple approach that I've used several times:
On the main html file, I load the default theme, for example the light one:
<link rel="stylesheet" href="/themes/light/theme.css" id="linkTheme" />
Then, on the theme changer button/menu option, I change the CSS file of the above link to load the corresponding one, something like:
const handleToggleTheme = (dark) => {
const lightUrl = "/themes/light/theme.css";
const darkUrl = "/themes/dark/theme.css";
if (dark) {
document.getElementById('linkTheme').setAttribute('href', darkUrl);
}
else {
document.getElementById('linkTheme').setAttribute('href', lightUrl);
}
}

How to set padding of Gatsby Link Component to 0px with styled-components

I have made some style changes to the Gatsby Link component using styled-components. However for some reason, when i try to apply a padding of 0px, it still leaves a tiny space (few px) above/below the text (between text and top/bottom border). I used gatsby-default-starter in a codesandbox for the initial build.
HTML/CSS Env (codepen.io):
https://codepen.io/marti2221/pen/mNVJWZ
Gatsby Env (codesandbox):
https://codesandbox.io/s/gatsby-paddinglink-spacing-gedtq
I have tried applying padding via styled-components in a Gatsby environment, as well as a normal html/css environment. When padding is set to 0px on the "a" tag in css/html environment, there is no space around the text, as expected. However when i attempt to add the same padding to the gatsby Link component or even a regular a tag, in a gatsby environment, there is a tiny space between the text and my border. This leads to a larger padding on top/bottom for my BtnLink than expected. I could adjust my padding accordingly, but i would like to know the root cause of this issue.
const StyledLink = styled(Link)`
display: inline-block;
font-family: sans-serif;
border-radius: 25px;
padding: 0px;
text-decoration: none;
border: 2px solid green;
`
const StyledA = styled.a`
display: inline-block;
font-family: sans-serif;
border-radius: 25px;
padding: 0px;
text-decoration: none;
border: 2px solid green;
`
const BtnLink = props => (
<StyledLink {...props}>{props.children}</StyledLink>
)
const IndexPage = () => (
<Layout>
<BtnLink to="page-2">Request Quote</BtnLink>
<StyledA href="page-2">Request Quotes</StyledA>
<Link to="page-2">Link</Link>
</Layout>
)
My desired result is a gatsby Link component that can be styled the same as a regular link element (ie. 0px padding). My result is link text with some spacing around it in the Gatsby environment. When tested with regular HTML/CSS, results are as expected (no spacing when padding is set to 0px)
You've already made a styled(Link) styledComponent, and saved it to the const StyledLink.
const StyledLink = styled(Link)`
display: inline-block;
font-family: sans-serif;
border-radius: 25px;
padding: 0px;
text-decoration: none;
border: 2px solid green;
However, this won't have any affect on a regular gatsby Link component. You still need to render this new StyledLink styledComponent instead of a gatsby Link component if you want to see that styled variation on your page.
const IndexPage = () => (
<Layout>
<BtnLink to="page-2">Request Quote</BtnLink>
<StyledA href="page-2">Request Quotes</StyledA>
<StyledLink to="page-2">Link</StyledLink>
</Layout>
)

Create and Display a Div using JQuery without distorting other elements

I am trying to create a div and show a timeout message in there. But it actually distorts other parts of Page. For eg see below. Session Timed out is the div with the message.
Now I don't want this to happen. PFB the JQuery code I am using to create this Div
function ShowSessionTimeOutDiv() {
var styler = document.createElement("div");
styler.setAttribute("style","font-size:15px;width:auto;height:auto;top:50%;left:40%;color:red;");
styler.innerHTML = "<b><i>Session TimedOut, Please refresh the Page</i></b>";
document.body.appendChild(styler);
var currentDiv = $('#GoToRequestControl1_UpdatePanel1').get(0);
currentDiv.parentNode.insertBefore(styler,currentDiv) ;
}
Am I missing something here? The Part in which this div is being displayed is coming from Master Page.
Have you tried the position:fixed styling on it in css, i did that on one of my websites and it didn't distort anything.
A page has a natural flow of its elements based on the default display rules specified by the W3C. When you add a div in between other elements it naturally affects the layout of the page; the positions of the other elements.
In order to drop in a new element without it affecting other elements you have to either reserve space for it, or take it out of the normal page flow.
There are a couple of ways to take an element out of the flow — you can float it, float:left or float:right, which is great, for example, to stack blocks on the left (instead of top-down) and let them wrap to new rows as available width changes. Using a flex layout gives you a lot of control also. But in this case of one thing popping up, changing the positioning of the new element is the most straightforward and can let you put the block exactly where you want it.
I have a demonstration and full explanation in a fiddle showing several examples along the way to getting what you want.
Basically, styling is needed to reposition the timeout message element that you're inserting. Styling is better done with CSS styles, compared to adding a bunch of inline styles. If I put my timeout popup message in a "messagebox" I can make a class for it.
/* Your styles, plus a couple extra to make the example stand out better */
div.messagebox {
font-size: 16px;
width: auto;
height: auto;
top: 40%;
left: 30%;
background-color: white;
border: 2px solid black;
}
Likewise, style the message itself with a class, instead of using inline styles and the deprecated presentational tags <b> and <i>.
/* I want the message in a messagebox to be bold-italic-red text. */
div.messagebox .message {
color: red;
font-style: italic;
font-weight: bold;
}
The big difference is that we will change the positioning of the element from the default static to instead use absolute positioning:
/* I don't really recommend a class called "positioned".
A class should describe the kind of thing the element *is*
not how it *looks*
*/
div.messagebox.positioned {
position: absolute;
width: 40%;
padding: 1.5em;
}
/* The container of the positioned element also has to be positioned.
We position it "relative" but don't move it from its natural position.
*/
section#hasposition {
position: relative;
}
The term "absolute" is tricky to learn ... the element being positioned is given an absolute position within its container, in a sense it's positioned relative to its container... but what position:relative means is relative to its own natural position, so it's easy to get confused at first over whether you want absolute or relative positioning.
Putting it all together, we have some basic HTML that represents major portions of a page — a real page will have far more, but those should be contained within some top-level containers. This shows only those top-level containers.
Then we have some javascript that will add the new element at the appropriate time. Here I just call the function to add it after a delay created with setTimeout(). I'm using full-on jQuery since you're using some in your example, and it makes the javascript more portable and more concise.
function ShowSessionTimeoutStyled() {
var styler = $('<div>').addClass('messagebox').addClass('positioned');
styler.html('<span class="message">The Session Timed Out</span>');
$('#hasposition .above').after(styler);
}
// wait 6 seconds then add the new div
setTimeout(ShowSessionTimeoutStyled, 6000);
div.messagebox {
font-size: 16px;
width: auto;
height: auto;
top: 20%;
left: 20%;
background-color: white;
border: 2px solid black;
}
div.messagebox .message {
color: red;
font-style: italic;
font-weight: bold;
}
div.messagebox.positioned {
position: absolute;
width: 40%;
padding: 1.5em;
}
section#hasposition {
position: relative;
}
/* also style some of the basic parts so you can see them better in the demonstration */
section.explanation {
margin: 1em 0.5em;
padding: 0.5em;
border: 1px solid gray;
}
.demonstration {
margin-left: 1em;
padding: 1em;
background-color: #e0e0e0;
}
.demonstration .above {
background-color: #fff0f0;
}
.demonstration .middle {
background-color: #f0fff0;
}
.demonstration .below {
background-color: #f0f0ff;
}
.demonstration footer {
background-color: white;
}
p {
margin-top: 0;
padding-top: 0;
}
section {
font-family: sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="explanation">
<p>Here, a div is added dynamically, after the "basic part above", but the added div is <em>positioned</em>. You can see the other content isn't affected.</p>
<section class="demonstration" id="hasposition">
<div class="above">Basic part above</div>
<div class="middle">Middle part</div>
<div class="below">Part Below</div>
<footer>This is the page footer</footer>
</section>
</section>
I highly recommend the site Position Is Everything for articles and tutorials on positioning. Some of its other content is outdated — who needs to make PNGs to do drop-shadows any more? — but the way positioning works hasn't changed.

Categories