I'm trying to change the text from black to blue when I click. I have it as an "if" statement and I know it doesn't need to be an "if" statement, but I'm just wondering why it doesn't work. I'm just asking, "If this color is black, change it to blue."
var myvar = document.getElementById('thisdiv');
myvar.onclick = function myfunction() {
if (myvar.style.color == "#000000") {
myvar.style.color = "#0000FF";
}
}
.mydiv {
height: 200px;
width: 200px;
background-color: red;
color: #000000;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
<div class="mydiv" id="thisdiv">Click Me</div>
JSFiddle
I'm not really looking for a solution to make it go from black to blue as I'm sure there's other ways I could figure out to do it, but more just wondering why the way I have it isn't working.
style only holds styles that were added using the style attribute in the HTML. It doesn't contain the computed style from applying <style> tags or stylesheets.
To get the computed style, use window.getComputedStyle(). Note this is read-only.
var myvar = document.getElementById('thisdiv');
myvar.onclick = function myfunction() {
if (window.getComputedStyle(myvar).color === "rgb(0, 0, 0)") {
myvar.style.color = "#0000FF";
}
}
.mydiv {
height: 200px;
width: 200px;
background-color: red;
color: #000000;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
<div class="mydiv" id="thisdiv">Click Me</div>
A better strategy though is to add or remove CSS classes to elements, so that you get separate presentation from functionality.
Okay, so the reason the code is not working is because myvar.style.color is undefined. When you use a stylesheet, it doesn't affect the JavaScript style properties, which should be the same as the styles defined in the style attribute of the element. What you want is something like the following.
// undefined!="#0000ff", success
if(myvar.style.color!="#0000ff") {
myvar.style.color = "#0000ff";
}
If you want to use JQuery, you can try something like the following.
// JQuery always returns opaque colors in rgb(r, g, b) form
// regardless of the original format.
if($(myvar).css("color")=="rgb(0, 0, 0)") {
myvar.style.color = "#0000ff";
}
I strongly suggest using an additional class for this, to account for its state.
var myvar = document.getElementById('thisdiv');
myvar.onclick = function myfunction() {
/* if (myvar.className === ""){
myval.className = "active";
} else {
myvar.className = "";
} */
// Same as below, toggle the class of #thisdiv from active to blank
myvar.className = myvar.className === "" ? "active" : "";
}
.mydiv {
height: 200px;
width: 200px;
background-color: red;
color: #000000;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.mydiv.active{
color: #0000ff;
}
You could also probably make use of the :visited pseudo selector and get rid of the click function entirely. You'd need to make your div one big link though. Something like this;
<a class="mydiv" id="thisdiv">Click Me</a>
.mydiv{
display:block; /* since it's a link and will be inline by default */
}
.mydiv:visited{
color: #0000ff;
}
Related
So I want to change a css value in javascript, without having an element in html, I'll explain like:
<style>
.box{
width: 10%;
}
</style>
<script>
// I want to change the width value of (.box) to something like "90%"
</script>
So what I mean to say is that I want to change the (.box) width value between the two style tags, I know my question sounds weird, but am just new coding and I really need it, any help appreciated!
Use media queries.
I don't remember the exact way to do this, but something like:
.box { width: 90%; }
#media screen and (min-width: 1000px) {
.box { width: 40%; }
}
You can change the properties (e.g. width) of a CSSStyleDeclaration with its setProperty() method.
You can get a CSSStyleSheet of a specific <style> element with its sheet property.
In our case, the stylesheet's first CSSStyleRule (sheet.cssRules[0]) is for the CSS class .box. You get the CSSStyleDeclaration object of a CSSStyleRule with its style property.
Example:
const iClass = document.getElementById("i-class");
const classRule = document.getElementById("my-style").sheet.cssRules[0];
// Set input.value to initial width-value (10%)
iClass.value = classRule.style.getPropertyValue("width");
// Update width-value on each input
iClass.addEventListener("input", () => {
classRule.style.setProperty("width", iClass.value);
});
/* Ignore; presentational styling */
.box {
margin-bottom: .5rem;
aspect-ratio: 1/1;
background-color: coral;
text-align: center;
}
<style id="my-style">
.box{
width: 10%;
}
</style>
<div>
<label for="i-class">Class width:</label> <input id="i-class">
</div>
<div class="box">class</div>
Unlike adding a new CSS rule, this changes the existing rule.
Here's one option, adding a <style> tag dynamically. This will add a style which overrides previous, obviously. See other answers for other options of changing existing rules.
var inline_style = `
.box {
width: 90%;
background: pink;
}`;
// from https://stackoverflow.com/a/28662118/3807365
document.head.insertAdjacentHTML("beforeend", '<style>' + inline_style + '</style>')
.box {
width: 10%;
background: blue;
}
<div class="box">i'm a box</div>
So I'm trying to implement a set of functions on my website with multiple div objects in it, so that when I click on Div A, it sets the text color of the page to red through Class A, and when i click on Div B, it sets the text to green through Class B, and so on and so forth.
My issue is that the other classes don't unset when clicking multiple objects and one class overrides the others, so the color of the text won't switch anymore.
I've been looking for solutions and trying to use addClass() and removeClass(), but it doesn't work for some reason. Here is a snippet of my code here
$(function() {
$('.one').click(function() {
$("h1").addClass('onetxt');
$("h1").removeClass('twotxt, threetxt');
});
});
$(function() {
$('.two').click(function() {
$("h1").addClass('twotxt');
$("h1").removeClass('onetxt, threetxt');
});
});
$(function() {
$('.three').click(function() {
$("h1").addClass('threetxt');
$("h1").removeClass('onetxt, twotxt');
});
});
h1 {
text-align: center;
}
div {
height: 65px;
width: 65px;
margin: 20px auto;
border-style: solid;
}
/*style info, ignore above here*/
.one {
background-color: red;
}
.onetxt {
color: red;
}
.two {
background-color: green;
}
.twotxt {
color: green;
}
.three {
background-color: blue;
}
.threetxt {
color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Sample Text</h1>
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
Any help on this would be greatly appreciated, and if you need more info, ask me in the replies, thank you!
EDIT: Here's a JSFiddle link demonstrating the code that i currently have, my intention is for all three of the DIV elements to change the top text's color when selected in any order, with using the classes if possible.
It seems like the main issue is that removeClass doesn't support multiple class selectors (like 'onetxt, twotxt'). Also you aren't removing all possible classes depending on the order of clicks.
Here's a solution that might work. I've written some helper functions which hopefully clarify what's going on.
const targets = 'h1, p'
const classmap = {
one: 'onetxt',
two: 'twotxt',
three: 'threetxt'
}
const allclasses = Object.values(classmap);
function clearSelection() {
allclasses.forEach(function(clz) { $(targets).removeClass(clz) });
}
function addSelection(sel) {
$(targets).addClass(classmap[sel]);
}
$(function() {
$('.one').click(function(){
clearSelection();
addSelection('one')
});
});
$(function() {
$('.two').click(function(){
clearSelection();
addSelection('two')
});
});
$(function() {
$('.three').click(function(){
clearSelection();
addSelection('three')
});
});
Here's a vanilla DOM API solution based on classList.toggle(className: string, force: boolean). The second parameter controls whether toggle works as remove or add.
const classes = ['one', 'two', 'three'];
classes.forEach(clazz => {
document.querySelector(`.${clazz}`).addEventListener('click', () => {
classes.forEach(cl => document.querySelector('h1').classList.toggle(`${cl}txt`, cl === clazz));
})
})
h1 {
text-align: center;
}
div {
height: 35px;
width: 35px;
margin: 5px auto;
border-style: solid;
}
/*style info, ignore above here*/
.one {
background-color: red;
}
.onetxt {
color: red;
}
.two {
background-color: green;
}
.twotxt {
color: green;
}
.three {
background-color: blue;
}
.threetxt {
color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Sample Text</h1>
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
There is no .removeClass() overload supports multiple argument, it only remove the first class. .removeClass() with no argument remove all the classes. This maybe the one you need.
I tweak your code a little bit, including:
Rename some class name. .color-palette is the container of all color selection. .color is individual color choice box.
Add data-color-name attribute to .color. The attribute will be used for sample-text css class assignment.
Simplify the click event with a single, event-delegate handler. I try to decouple the add/remove class logic with the actual color name. This way if you have more color boxes to add, you do not need to copy a new set of function.
Define custom css property. E.g. (--color-1, --color-2). The same property is used for color box background and sample text font color. You don’t have to maintain colors in two different place.
$('.color-palette').on('click', '.color', function(e) {
$("#sample-text").removeClass().addClass($(e.currentTarget).data('color-name'));
});
/* maintain the color choices here */
:root {
--color-1: red;
--color-2: green;
--color-3: blue;
}
h1 {
text-align: center;
}
.color {
height: 65px;
width: 65px;
margin: 20px auto;
border-style: solid;
}
/* style info, ignore above here */
/* color palette style */
.color.color-1 {
background-color: var(--color-1);
}
.color.color-2 {
background-color: var(--color-2);
}
.color.color-3 {
background-color: var(--color-3);
}
/* sample text style */
#sample-text.color-1 {
color: var(--color-1);
}
#sample-text.color-2 {
color: var(--color-2);
}
#sample-text.color-3 {
color: var(--color-3);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id="sample-text">Sample Text</h1>
<div class="color-palette">
<div class="color color-1" data-color-name="color-1"></div>
<div class="color color-2" data-color-name="color-2"></div>
<div class="color color-3" data-color-name="color-3"></div>
</div>
Building a website that will contain others’ work. I want to know if my background receives a click, did they click on something like a button or something with a click handler. I know how to stop events from propagating but I do not want to require that in their code. How would you advise I handle the problem to see if they click something inside the doc but want to know if they clicked on an element inside something interactive that already did something in response to the click?
If I'm reading your question correctly, you want to perform an action to certain elements so long as they aren't nested in elements with inherent on click functions?
If that's the case, you could recursively check all the tag types
function handleClick(e) {
const target = e.target;
function recursive(node) {
if (node.id === "stop") return true;
if (["A", "BUTTON"].indexOf(node.tagName) > -1) return false;
return recursive(node.parentNode)
}
console.log(recursive(target));
}
body {
width: 100%;
height: 100%;
background: lightgray;
display: flex;
flex-direction: column;
}
div,
a {
padding: 10px;
box-sizing: border-box;
display: flex;
flex-direction: column;
width: 100%;
height: 100px;
background: gray;
}
a {
background: darkgray;
}
p {
width: 100%;
background: white;
}
button {
width: 80px;
}
<body id="stop" onclick="handleClick(event)">
body
<a>
anchor
<button>buttonA</button>
<p>textA</p>
</a>
<div>
div
<button>buttonB</button>
<p>textB</p>
</div>
</body>
textB should return true since its in a div, while textA should return false since its in an anchor.
I've got a simple text button with an image of an arrow next to it. I'm wanting the arrow image to move when someone hovers over the button.
I currently have this working in one instance with JS 'document.getElementById...', but I have several buttons across my site that I'd like to have the same behavior. My first thought would be to use a class instead of an id, and use the same functions.
For whatever reason, document.getElementsByClassName doesn't work - even in one instance.
Here's a simpler version to demonstrate - View on Codepen: https://codepen.io/sdorr/pen/JxYNpg
HTML
<HTML>
hover over me
<div id="block"></div>
hover over me
<div class="block"></div>
CSS
* {
margin: 0;
padding: 0;
}
.button {
color: #000000;
text-decoration: none;
background-color: cyan;
margin: 0;
display: block;
width: 300px;
padding: 20px;
text-align: center;
}
#block {
width: 30px;
height: 30px;
background-color: red;
}
.block {
width: 30px;
height: 30px;
background-color: green;
}
JS
function move() {
document.getElementById("block").style.marginLeft = "35px";
}
function moveBack() {
document.getElementById("block").style.marginLeft = "0px";
}
function moveAlt() {
document.getElementsByClassName("block").style.marginLeft =
"35px";
}
function moveBackAlt() {
document.getElementsByClassName("block").style.marginLeft =
"0px";
}
First off, why isn't the behavior with a class working but an id works fine?
Secondly, would a class solve this issue and be scalable across all buttons with the same two functions (onmouseover / onmouseout)?
If not, any ideas on a solution? I currently have a solution I found using jQuery that does work, but when hovering over one button, all arrow images move across the site. I don't necessarily mind this behavior because only one button is really in view at a time - but I'm trying to learn JS and solve problems with my own solutions!
I greatly appreciate your desire to learn on your own and not rely on premade solutions. Keep that spirit and you will go places!
When it comes to getElementsById, we know this should work for one element, since the function returns a single Element.
However, what does getElementsByClassName return?
(see: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName)
It returns an HTMLCollection which you can iterate over to change an single element's style.
So, to get this to work with JavaScript you need to write a function that will be able to identify the particular div.block you want to move. But, this puts you back to where you started, needing some particular identifier, like an id or a dataset value to pass to the function.
Alternately, based on the HTML structure you provide, you could look for nextElementSibling on the a that get's clicked. But I would set up an eventListener rather than adding a JS function as a value to the onmouseenter property.
const btns = document.getElementsByTagName('a');
/*** UPDATE forEach is a NodeList method, and will fail on HTMLCollection ***/
/* this fails -> Sorry! ~~btns.forEach(button=>{~~
/* the following will work
/**********/
for (let i = 0; i < btns.length; i++){
btns[i].addEventListener('mouseenter', function(e) {
//we pass e to the function to get the event and to be able to access this
const block = this.nextElementSibling;
block.style.marginLeft = "35px";
})
btns[i].addEventListener('mouseleave', function(e) {
const block = this.nextElementSibling;
block.style.marginLeft = "0";
})
}
But with siblings, there is a CSS-only solution.
We can use the Adjacent Sibling Selector combined with the :hover state selector and no JavaScript is needed, if we are just moving back and forth.
.button:hover+.block {
margin-left: 35px;
}
See the Snipped Below
* {
margin: 0;
padding: 0;
}
.button {
color: #000000;
text-decoration: none;
background-color: cyan;
margin: 0;
display: block;
width: 300px;
padding: 20px;
text-align: center;
}
.block {
width: 30px;
height: 30px;
background-color: green;
}
.button:hover+.block {
margin-left: 35px;
}
hover over me
<div class="block"></div>
hover over me
<div class="block"></div>
As Vecta mentioned, getElementsByClassName returns an array-like. You'll need to do something like this to get the first element:
function moveAlt() {
document.getElementsByClassName("block")[0].style.marginLeft = "35px";
}
function moveBackAlt() {
document.getElementsByClassName("block")[0].style.marginLeft = "0px";
}
However a better solution might be to use document.querySelector, which operates similarly to jQuery's $() syntax:
function moveAlt() {
document.querySelector(".block").style.marginLeft = "35px";
}
function moveBackAlt() {
document.querySelector(".block").style.marginLeft = "0px";
}
I'm trying to do something, like when you Mouseover on text inside a span, the background changes.
My code:
<script>
function unhighlight(x) {
x.style.backgroundColor="transparent"
}
function highlight(x) {
x.style.backgroundColor="red"
}
</script>
<span onmouseover="highlight(this)" onmouseout="unhighlight(this)">
<h2>What's New</h2>
</span>
The reason I don't apply it to the h2 is a little complicated. Don't need to explain. Help?
Your javacript is fine.
The span element is the inline level generic container. It also helps
to inform the structure of document, but it is used to group or wrap
other inline elements and/or text, rather than block level elements.
So h2 is not valid child for span:
html standard
function unhighlight(x) {
x.style.backgroundColor = "transparent"
}
function highlight(x) {
x.style.backgroundColor = "red"
}
span {
display: block;
}
<span onmouseover="highlight(this);" onmouseout="unhighlight(this)"><h2>What's New</h2></span>
I suggest for containers to use block elements like div. And also i suggest to use css for this:
div:hover {
background: red;
}
<div>
<h2>What's New</h2>
</div>
Just set CSS to <span>
display: block;
You need to change your span element to an inline block for this to work :
span {
display: inline-block;
}
But note that you can achieve the same effect with CSS only :
span {
display: inline-block;
background-color: transparent;
}
span:hover {
background-color: red;
}
You don't need javascript to do it, just with HTML and CSS :
#myText {
display: inline-block;
background-color: transparent;
}
#myText:hover {
display: inline-block;
background-color: red;
}
<span id="myText"><h2>What's New</h2></span>