Changing hover background color with javascript - javascript

I want to access the hover background color of a button to change the hover background color every time the button is clicked.
This is the button tag from the index.html file
<button class="btn-hero btn-hero:hover" id="btn">click me</button>
This is in the css file:
.btn-hero {
font-family: var(--ff-primary);
text-transform: uppercase;
background: transparent;
color: var(--clr-black);
}
.btn-hero:hover {
color: var(--clr-white);
background: var(--clr-black);
}
I can access the button background color like this:
btn.addEventListener("click", function () {
btn.style.backgroundColor = 'some_color'
});
That changes the button color but negates the hover property.
I tried doing this in the app.js:
let button_hover = document.querySelector(".btn-hero:hover")
But that returns a null.
Is there a way to do access the hover properties from the css file in app.js file?

Answer
In terms of javascript you can use mouseover event handler
Example
btn.addEventListener("mouseenter", function( event ) {
event.target.style.color = "purple";
}, false);
btn.addEventListener("mouseleave", function( event ) {
event.target.style.color = "";
}, false);
Reference
MDN : mouseover event

The snippets your posted contain a few errors in both the JS and the HTML:
HTML
<button class="btn-hero" id="btn">click me</button> should not contain :hover as this is a CSS pseudo selector (in this case connected to btn-hero) and should only be used in CSS (or referenced by Javascript). Remove the btn-hero:hover.
Javascript
If you want to 'catch' the element hover event you need to attach an eventListener (in case of hover either mouseover or mouseenter) to the button
While document.querySelector(".btn-hero:hover") is a proper selector, but due to the asynchrous nature of Javascript it would be purely accidental that the hover would be caught when the JS function runs. That is why the function returns NULL.
If you want to modify the CSS style of an element, digg into MDN: Window.getComputedStyle()
CSS
Seems okay to me.
Your question
Please make sure you understand that the hex value of a color is essentially not one long hexadecimal value, but a concatenation of 3 hex values resembling R,G,B made up of 2 hexadecimal digits each. Adding 100hex to any #xxxxxx (6 digit) color would get rather unexpected results. Which of the three (R,G,B) do you want to change?

So you want each button click to change the background a bit. I did not understand your hex point, but here is one of the scripts, that calculates background color from given numeric value. In this case its the attribute data-colorvalue
I modified it to fit your case and made it so it adds 10 each click. You can play around the math here, that way you get different colors:
// Grab the button:
const btn = document.querySelector('#btn')
// Detect on click event:
btn.onclick = e => {
// Get the buttons color value, parseInt makes sure its INT:
let color_value = parseInt(btn.getAttribute('data-colorvalue'))
// Make the R value based on color_value:
val_r = Math.round((255 * color_value) / 100)
// Make the G value based on color_value:
val_g = Math.round((255 * (100 - color_value)) / 100)
// Make the B value based on color_value:
val_b = Math.round(255 - (color_value * 1.5))
// Format and set as buttons background:
btn.style.backgroundColor = 'rgb(' + val_r + ', ' + val_g + ', ' + val_b + ')'
// Set the new color value plus 10.. you can play with this formula:
btn.setAttribute('data-colorvalue', color_value + 10)
}
<button id="btn" data-colorvalue="1">Click me</button>
If you want to change the hover as pseudo, then you need magic. And thats a completely standalone quesiton.
Your title says text color and question background, color. So if you want to change the text / font color you simply use btn.style.color instead of backgroundColor.
Psedo classes do not go to your html like so, ever:
EDIT
Based on the additional information provided in the comments, we worked out, that you want to change the hover-background-color each time the button is clicked.
This is a very strange situation and odd request. But one of the ways doing it is making new style element contents on each click like so:
// Grab the button:
const btn = document.querySelector('#btn')
// Make style element:
let style = document.createElement('style')
// Detect on click event:
btn.onclick = e => {
// Get the buttons color value, parseInt makes sure its INT:
let color_value = parseInt(btn.getAttribute('data-colorvalue'))
// Make the R value based on color_value:
val_r = Math.round((255 * color_value) / 100)
// Make the G value based on color_value:
val_g = Math.round((255 * (100 - color_value)) / 100)
// Make the B value based on color_value:
val_b = Math.round(255 - (color_value * 1.5))
// Set the new color value plus 10.. you can play with this formula:
btn.setAttribute('data-colorvalue', color_value + 10)
// Now starts the magic...
// Make the css contents for the style element:
let css = '#btn:hover{background-color:rgb(' + val_r + ', ' + val_g + ', ' + val_b + ')}'
// If style element exists already, then lets overwrite its contents:
if (style != undefined) style.innerHTML = css
// .. however if there is none, then we must append new:
else style.appendChild(document.createTextNode(css))
// Now we simply append the style element to the head:
document.getElementsByTagName('head')[0].appendChild(style)
}
<button id="btn" data-colorvalue="1">Click me</button>

You can use !important, but you may want to refactor your code by setting CSS variables with JavaScript or using mouseenter and mouseleave event handlers.
const btn = document.querySelector('#btn');
btn.style.backgroundColor = 'red'
:root {
--clr-black: black;
--clr-white: white;
}
.btn-hero {
font-family: var(--ff-primary);
text-transform: uppercase;
background: transparent;
color: var(--clr-black);
}
.btn-hero:hover {
color: var(--clr-white);
background: var(--clr-black) !important;
}
<button class="btn-hero" id="btn">click me</button>

Related

EventListener Only Firing Once

still learning the basics of JS, working with EventListeners now. Trying to make a button that changes the color of text back and forth but I think I'm misunderstanding the nature of the method, or using it incorrectly. I don't believe it's a syntax issue.
I have the text and the button, both with Id's. I created variables for both elements. I add an event listener to the button, and defined the if else statement in the function. The "if" portion of the function executes without issue, but that's where it ends. Sorry in advance for the formatting I wasn't sure what made the most sense. Thanks!
Here's the HTML:
<h1 id="header"> Here's some text </h1>
<button id="button"> Change the Color </button>
CSS:
#header {
color: red;
}
And the JavaScript:
var header = document.getElementById("header");
var button = document.getElementById("button");
button.addEventListener("click", function() {
if (header.style.color = "red")
{header.style.color = "blue";}
else if (head.style.color = "blue")
{header.style.color = "red";
}
})
In JavaScript (and other languages) you need to use == to check for equality.
However, in JavaScript there is also ===. === is the strict equality operator, meaning it does not do type conversion. What does that mean? It means:
"5" == 5 // true, since "5" as a number is equal to 5, the literal number
"5" === 5 // false, since a string cannot equal a number
So in your if statements you should use == or === instead of just =.
Others have mentioned the use of = vs == vs === - which is definitely your problem, but you're also going to have other problems with comparing styles the way you are doing.
The style property is unique and cumbersome. You have the "style" property which is a property of the DOM node (just like href for anchors or type for inputs). Then you have styles which are applied from a stylesheet - either a <style> tag or external stylesheet file. Sometimes the two different styles sources are in conflict.
For style properties, you read the node.style.color property like you are doing. To get the actual color being applied to the node, you must use window.getComputedStyle(). Let me explain the difference by example:
const div = document.getElementById('foo')
div.style.color; //-> red
window.getComputedStyle(div).color; //-> rbg(0, 255, 0) - this is green!
#foo { color: green !important }
<div id="foo" style="color: red">Hello!</div>
Notice how we set red on the node itself, but green !important in the stylesheet. The !important will win, which is why the text is green. Furthermore, the browser converts the color name green to its RGB equivalent rgb(0, 255, 0). This can be tedious to reconcile. What I usually recommend is having multiple class names and switching between those on click:
var header = document.getElementById("header");
var button = document.getElementById("button");
button.addEventListener("click", function() {
if (header.classList.contains("red")) {
header.classList.remove("red")
header.classList.add("blue")
} else if (header.classList.contains("blue")) {
header.classList.remove("blue")
header.classList.add("red")
}
})
.red { color: red }
.blue { color: blue }
<h1 id="header" class="red"> Here's some text </h1>
<button id="button"> Change the Color </button>

How to console.log multiple objects?

I am creating a javascript exercise, my idea was to create a function that would give me an icon return, I am using FontAwesome for this. I managed to make it show the icon and the message but I wanted to add my predefined styles for titles, emphasis .. etc through a function but I still can't think of a form. I even tried using Swith but it only copies css as any string
function icones(ico_name, text,style ){ // Capture icon name, style to be used and text
switch(ico_name) { //Check argument icon
case 'user':
ico_name = '%c ' //Icon will only be displayed after CSS declaration
font = 'font-family: "Font Awesome 5 Free"; font-weight: 900; font-size: 20px; content: "\f434";'
break
}
switch(style) { // Styling text
case 'title':
text = 'color: red'
break
}
console.log(ico_name,font,text)
}
icones('user','player', 'title') //Applying values to function
I'm not sure if this is what you are looking for, but you can use document.getElementById() to get an element in the webpage and then apply CSS styles.
For instance, if the element whose font you are trying to change has its id attribute set to "changeMyFont":
<span id="changeMyFont"></span>
you can change its CSS attributes using JavaScript as such:
var elem = document.getElementById("changeMyFont");
elem.style.fontFamily = "Font Awesome 5 Free";
elem.style.fontWeight = 900;
elem.style.fontSize = "20px";
To change the text color to red for a certain element, you can follow the same procedure. To change the content within a HTML tag, use innerHTML (do not allow user input here; it is an XSS threat):
document.getElementById("elementToChange").innerHTML = "HTML here";
You can use an HTML escape in there.
Well after a few hours between trial and error I was able to accomplish my feat.
The "secret" was to put 2 styles in just one console.log, the code may seem like a confusing drift and surely to improve it.
function icones(ico_nome,texto,style ){ // Captura o nome do icone, o estilo que sera utilizado e o texto
switch(ico_nome) { // Check argument icon
case 'user':
ico_nome = '%c ' // Icon will only be displayed after CSS declaration
font_icon = 'font-family:"Font Awesome 5 Free"; font-weight: 900; font-size: 20px;' //Declara a fonte para visualização
break
}
switch(style) { // Styling text
case 'titulo': // Set styles for titles
font_icon += 'color:red;' //Set the color Red to Icon
style_text = 'color:blue; font-family: Arial;' // Set styles for texts
break
default:
font_icon += 'color: black' // Set default color
}
console.log(ico_nome + ' ' + '%c' + texto,font_icon,style_text) //Join the 2 styles and reveal the output
}
icones('user','Usuario', 'titulo') //Applying values to function
Final result
---- Console Output
Still do not know how to insert the image directly into the post sorry :)
Use Jquery function .css() For example:
$("#element").css("font-size", "20pt")

Get color of DIV in hex format JQuery

This is my code:
function getTraits(trait) {
$("#"+trait).on("click", function() {
alert($(this).css('backgroundColor'));
if (toHex($(this).css('background-color')) != highlightedColor) {
$("#"+trait).css("background-color", highlightedColor);
// If the element isn't highlighted, highlight it.
} else {
$(this).css("backgroundColor", defaultColor);
}
})
}
I am trying to toggle a highlight on a div on the user's click. I would like to get the background color of the div because it would be inefficient to store a boolean toggle for each and every div. So I want a toHex(rgb) function. I saw a lot of those on SO, so I tried using them and none of them worked. The alert() I put to show me the format JQuery was returning gave me rgba(0,0,0,0). I attempted to modify a regex I found like this:
var rgb = rgb.match(/^rgba((\d+),\s*(\d+),\s*(\d+))$/);
That failed to work with a TypeError: rgb is null.
Thanks for any help you can give me!
I know, not the answer to your question, but have you considered jQuery's toggleClass() option?
Define a highlighted CSS class:
DIV.default { background-color: whitesmoke; }
DIV.highlighted { background-color: yellow; }
and then when the user clicks your DIV:
function getTraits(trait) {
$("#"+trait).on("click", function() {
// Toggle both classes so as to turn one "off"
// and the other "on"
$(this).toggleClass('default');
$(this).toggleClass('highlighted');
// Ensure we have at least one class (default)
var hasOne = $(this).hasClass('highlighted') || $(this).hasClass('default');
if (!hasOne) {
$(this).addClass('default');
}
})
}
First of all get Background-Color and use the below function to convert it into HEX Value
var rgb=$(selector).css('background-color');
var hexColor=rgb2hex(rgb);
function rgb2hex(rgb) {
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
return (rgb && rgb.length === 4) ? "#" +
("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) +
("0" + parseInt(rgb[3], 10).toString(16)).slice(-2) : '';
}
Your problem: jquery will return rgba(0, 0, 0, 0) if there is no background color set (i.e. it is undefinied / null). The problem you have is that you are trying to parse an undefined rgb string into the hex converter.
I've added a clause into the converted from here, so that it returns white if the value is unset but this would need uncommenting, and isn't advised.
Advised solution is to use toggleClass, see the demo further down, showing how you can toggle higlighting on indiviidual elements or entire DOM trees.
Demo of rgb issue
// Cycle through each div
$("#example-wrap div").each(function() {
// Store rgb color
var rgb = $(this).css('backgroundColor');
// Print rgb color to the div
$(this).append( ": " + rgb);
// Append the hex value
$(this).append(" -> " + rgb2hex(rgb));
});
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
// Check if rgb is null
if (rgb == null ) {
// You could repalce the return with a default color, i.e. the line below
// return "#ffffff"
return "Error";
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
#example-wrap div {
border: 1px solid black;
width: 100%;
height: 50px;
color: black;
}
#example-wrap .background-blue {
background: blue;
color: white;
}
#example-wrap .background-white {
background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="example-wrap">
<div id="background-set" style="background-color: red; color: white;">Background set in 'style' attribute</div>
<div id="background-class" class="background-blue">Background set to blue via class</div>
<div id="background-class" class="background-white">Background set to white via class</div>
<div id="background-none">No background set</div>
</div>
Highlight via Toggle Class
This example lets you highlight individual elements tagged with .highlightable, as well as applying wrappers which mean all their children are highlightable via the class .highlightable-wrapper.
// Add click event to highlightable elements and wrappers
$(document).on("click", ".highlightable, .highlightable-wrapper *", function(e) {
// Toggle highlight class
$(this).toggleClass("highlight-me");
// Stop click event from propogating (i.e. allow spans to be highlighted individually)
// Uncomment this if you want propogation
e.stopPropagation()
});
.highlight-me {
color: blue;
}
.highlightable-wrapper .highlight-me, .highlightable-wrapper .highlight-me * {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="example-wrapper">
<div class="highlightable">
<h4>Individual Element Example</h4>
This is an exampled of a div with the .highlightable class.
</div>
<hr style="margin: 20px 0px;">
<div class="highlightable-wrapper">
<h4>Wrapper Example</h4>
<p>I am a paragraph within an element with the .highlightable-wrapper class.</p>
<p>Click us to see us change <strong>I am a strong span, you can individually highlight me</strong>.</p>
</div>
</div>

What is the best method of changing the color of an SVG element by modifying the CSS code in a way that changes the Javascript code?

I've been writing a codepen for the game Simon and I was asked to rewrite it so that if somebody like an artist that was working with me had access to the html and css but didn't know how javascript worked (or didn't have access to the .js files) wanted to change the colors of the buttons they could do so w/o changing the javascript code. So my plan is to write the js code such that it adds/removes classes that affect the path elements. The path elements are like this:
<path class="outer arc1default" id="arc1"/>
with these css classes:
.outer {
stroke: black;
stroke-width: 10;
}
.arc1default {
fill: red;
}
if the color changes on click by design, this class gets added:
.arc1flash {
fill: pink;
}
On line 73 of the .js code I'm using the following:
function buttonFlash(button) {
console.log("button is: " + button);
//$("#" + button).attr("class", button + "flash outer");
//$("#" + button).removeClass(button + "default");
$("#" + button).addClass(button + "flash");
//$("#" + button).css({ fill: buttonDict[button].flash });
buttonDict[button].sound.play();
setTimeout(function() {
$("#" + button).attr("class", button + "default outer");
//$("#" + button).css({ fill: buttonDict[button].color });
buttonDict[button].sound.pause();
buttonDict[button].sound.currentTime = 0;
}, 300);
}
The code in // notation is what I was trying before and wasn't working at the time but I've left it in for reference in case I missed something and used it incorrectly but was on the right path.
Anyway, here's the results I've observed:
If I start the element w/ fill:red using the id in CSS, it starts red and stays red when classes get added/removed.
If I remove that part of the code but start the path element w/ a class that says fill:red then it starts red again (which is good) but when classes get removed/added nothing changes.
If I remove the fill:red from the element and do NOT add the class in question, it starts as if it has fill:black, probably because the outer class does a stroke: black for the border.
Here's the link to my codepen in case that helps: https://codepen.io/glennqhurd/pen/EQqxKe
To reiterate, I'm not asking about how to use Javascript to change the CSS. I'm asking how to use Javascript to change the classes of the HTML objects in such a way to change the properties of the objects w/o changing the classes themselves.
You have to use .attr() on a svg... Since .addClass() and .removeClass does not work. See this other answer about it.
Now you have to use the same class "name structure" on the 4 colors (like arc1default and arc1flash) if you want to concatenate default/flash to the button.
I updated your CodePen
function buttonFlash(button) {
console.log("button is: " + button);
$("#" + button).attr("class", "outer " + button + "flash");
buttonDict[button].sound.play();
setTimeout(function() {
$("#" + button).attr("class", "outer " + button + "default");
buttonDict[button].sound.pause();
buttonDict[button].sound.currentTime = 0;
}, 300);
}

jQuery animate issue

My function looks like that
$.fn.animateHighlight = function(highlightColor, originalColor, type, duration) {
var highlightBg = highlightColor || "#FFFF9C";
var animateMs = 500;
var animateVal1 = {};
animateVal1[type] = highlightColor;
var animateVal2 = {};
animateVal2[type] = originalColor;
this.stop().animate(animateVal1, animateMs).delay(duration).animate(animateVal2, animateMs);
};
Calling this like that
$("#variants").animateHighlight("red", "#9c9c9c", "borderColor", 3000);
The problem is,
This is default border color of fieldset
And this is after animation color
I know that animate adds extra style attribute to element. What I wanna do is, return back original fieldset border color (removing style attribute will return back original border color).
Tried to change last line of function to this
this.stop().animate(animateVal1, animateMs).delay(duration).animate(animateVal2, animateMs).removeAttribute('style');
Animate didn't even start.
How can I animate and reset back to original version after flashing?
this.stop().animate(animateVal1, animateMs).delay(duration).animate(animateVal2, animateMs, function() {
this.removeAttribute('style');
});
I think the two method for this.
1.If you used border color in stye attribute for VariantDiv.Default Styles will be lost in style when you remove style attribute. So you should hold first border color.
For Example :
http://jsfiddle.net/tEwa9/
2.if when you don't use style you can do this way.
You can call this code when animate completed.
$(this).attr('style','');
For example:
http://jsfiddle.net/xSYWS/

Categories

Resources