Change styling of a psuedo after element with javascript - 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');
}

Related

Toggling iron-collapse using 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.

Manipulating CSS with JavaScript

I would like to use JavaScript to manipulate my CSS. First it was just thought to be a nice little script to try out different colors for my accordion menu together with different backgrounds/title-/content-/... background-colors from an input field.
I understand how I get the input value with js.
I understand how CSS is manipulated by using getElementById(), getElementsByClassName(), getElementsByTag(), and getElementsByName().
Now, the problem is that my CSS looks like this:
.accordion li > a {
/* some css here */
}
.sub-menu li a {
/* some css here */
}
.some-class hover:a {
/* css */
}
.some-other-class > li > a.active {
/* css */
}
How would I change the properties of such stylings with JavaScript?
There's no way to manipulate some CSS styles directly with JavaScript. Instead you can change a rule in a stylesheet itself, something like this:
var changeRule = function(selector, property, value) {
var styles = document.styleSheets,
n, sheet, rules, m, done = false;
selector = selector.toLowerCase();
for(n = 0; n < styles.length; n++) {
sheet = styles[n];
rules = sheet.cssRules || sheet.rules;
for(m = 0; m < rules.length; m++) {
if (rules[m].selectorText.toLowerCase() === selector) {
done = true;
rules[m].style[property] = value;
break;
}
}
if (done) {
break;
}
}
};
changeRule('div:hover', 'background', '#0f0');
selector must match exactly an exisiting selector, only spaces between selector text and { are ignored.
You can develope the code to find and change partial hits of selector names, or just check a particular stylesheet instead of all of them. As it is, it's also quite expensive when having tens of stylesheets with thousands of rules.
Unfortenately pseudo elements can't be manipulated with this snippet.
A live demo at jsFiddle.
All DOM elements have a style object that can be altered by JavaScript
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.style?redirectlocale=en-US&redirectslug=Web%2FAPI%2Felement.style
Or if you're using jQuery:
http://api.jquery.com/css/
You can target elements and manipulate their propertoes, but you do not alter the rules.
A common approach if you want to alter large numbers of style properties is to alter elements' class names to change their appearance. This can be done with the className property, or if you're using jQuery: addClass and removeClass.
I've implemented Teemu's answer with underscore. http://jsfiddle.net/6pj3g/4/
var rule = _.chain(document.styleSheets)
.map(function(sheet){return _.flatten(sheet.cssRules)})
.flatten()
.unique()
.find(function(rule){ return rule && rule.selectorText && (rule.selectorText.toLowerCase() === selector.toLowerCase())})
.value()
if (rule){
rule.style[property] = value;
} else {
throw 'selector not found: ' + selector;
}

Change :hover CSS properties with JavaScript

How can JavaScript change CSS :hover properties?
For example:
HTML
<table>
<tr>
<td>Hover 1</td>
<td>Hover 2</td>
</tr>
</table>
CSS
table td:hover {
background:#ff0000;
}
How can the td :hover properties be modified to, say, background:#00ff00, with JavaScript? I know I could access the style background property using JavaScript with:
document.getElementsByTagName("td").style.background="#00ff00";
But I don't know of a .style JavaScript equivalent for :hover.
Pseudo classes like :hover never refer to an element, but to any element that satisfies the conditions of the stylesheet rule. You need to edit the stylesheet rule, append a new rule, or add a new stylesheet that includes the new :hover rule.
var css = 'table td:hover{ background-color: #00ff00 }';
var style = document.createElement('style');
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
document.getElementsByTagName('head')[0].appendChild(style);
You can't change or alter the actual :hover selector through Javascript. You can, however, use mouseenter to change the style, and revert back on mouseleave (thanks, #Bryan).
Pretty old question so I figured I'll add a more modern answer. Now that CSS variables are widely supported they can be used to achieve this without the need for JS events or !important.
Taking the OP's example:
<table>
<tr>
<td>Hover 1</td>
<td>Hover 2</td>
</tr>
</table>
We can now do this in the CSS:
table td:hover {
// fallback in case we need to support older/non-supported browsers (IE, Opera mini)
background: #ff0000;
background: var(--td-background-color);
}
And add the hover state using javascript like so:
const tds = document.querySelectorAll('td');
tds.forEach((td) => {
td.style.setProperty('--td-background-color', '#00ff00');
});
Here's a working example https://codepen.io/ybentz/pen/RwPoeqb
What you can do is change the class of your object and define two classes with different hover properties. For example:
.stategood_enabled:hover { background-color:green}
.stategood_enabled { background-color:black}
.stategood_disabled:hover { background-color:red}
.stategood_disabled { background-color:black}
And this I found on:
Change an element's class with JavaScript
function changeClass(object,oldClass,newClass)
{
// remove:
//object.className = object.className.replace( /(?:^|\s)oldClass(?!\S)/g , '' );
// replace:
var regExp = new RegExp('(?:^|\\s)' + oldClass + '(?!\\S)', 'g');
object.className = object.className.replace( regExp , newClass );
// add
//object.className += " "+newClass;
}
changeClass(myInput.submit,"stategood_disabled"," stategood_enabled");
Sorry to find this page 7 years too late, but here is a much simpler way to solve this problem (changing hover styles arbitrarily):
HTML:
<button id=Button>Button Title</button>
CSS:
.HoverClass1:hover {color: blue !important; background-color: green !important;}
.HoverClass2:hover {color: red !important; background-color: yellow !important;}
JavaScript:
var Button=document.getElementById('Button');
/* Clear all previous hover classes */
Button.classList.remove('HoverClass1','HoverClass2');
/* Set the desired hover class */
Button.classList.add('HoverClass1');
If it fits your purpose you can add the hover functionality without using css and using the onmouseover event in javascript
Here is a code snippet
<div id="mydiv">foo</div>
<script>
document.getElementById("mydiv").onmouseover = function()
{
this.style.backgroundColor = "blue";
}
</script>
You can use mouse events to control like hover.
For example, the following code is making visible when you hover that element.
var foo = document.getElementById("foo");
foo.addEventListener('mouseover',function(){
foo.style.display="block";
})
foo.addEventListener('mouseleave',function(){
foo.style.display="none";
})
I'd recommend to replace all :hover properties to :active when you detect that device supports touch. Just call this function when you do so as touch()
function touch() {
if ('ontouchstart' in document.documentElement) {
for (var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
var sheet = document.styleSheets[sheetI];
if (sheet.cssRules) {
for (var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
var rule = sheet.cssRules[ruleI];
if (rule.selectorText) {
rule.selectorText = rule.selectorText.replace(':hover', ':active');
}
}
}
}
}
}
This is not actually adding the CSS to the cell, but gives the same effect. While providing the same result as others above, this version is a little more intuitive to me, but I'm a novice, so take it for what it's worth:
$(".hoverCell").bind('mouseover', function() {
var old_color = $(this).css("background-color");
$(this)[0].style.backgroundColor = '#ffff00';
$(".hoverCell").bind('mouseout', function () {
$(this)[0].style.backgroundColor = old_color;
});
});
This requires setting the Class for each of the cells you want to highlight to "hoverCell".
I had this need once and created a small library for, which maintains the CSS documents
https://github.com/terotests/css
With that you can state
css().bind("TD:hover", {
"background" : "00ff00"
});
It uses the techniques mentioned above and also tries to take care of the cross-browser issues. If there for some reason exists an old browser like IE9 it will limit the number of STYLE tags, because the older IE browser had this strange limit for number of STYLE tags available on the page.
Also, it limits the traffic to the tags by updating tags only periodically. There is also a limited support for creating animation classes.
Declare a global var:
var td
Then select your guiena pig <td> getting it by its id, if you want to change all of them then
window.onload = function () {
td = document.getElementsByTagName("td");
}
Make a function to be triggered and a loop to change all of your desired td's
function trigger() {
for(var x = 0; x < td.length; x++) {
td[x].className = "yournewclass";
}
}
Go to your CSS Sheet:
.yournewclass:hover { background-color: #00ff00; }
And that is it, with this you are able to to make all your <td> tags get a background-color: #00ff00; when hovered by changing its css propriety directly (switching between css classes).
For myself, I found the following option: from https://stackoverflow.com/a/70557483/18862444
const el = document.getElementById('elementId');
el.style.setProperty('--focusHeight', newFocusHeight);
el.style.setProperty('--focusWidth', newFocusWidth);
.my-class {
--focusHeight: 32px;
--focusWidth: 256px;
}
.my-class:focus {
height: var(--focusHeight);
width: var(--focusWidth);
}
You can make a CSS variable, and then change it in JS.
:root {
--variableName: (variableValue);
}
to change it in JS, I made these handy little functions:
var cssVarGet = function(name) {
return getComputedStyle(document.documentElement).getPropertyValue(name);
};
and
var cssVarSet = function(name, val) {
document.documentElement.style.setProperty(name, val);
};
You can make as many CSS variables as you want, and I haven't found any bugs in the functions;
After that, all you have to do is embed it in your CSS:
table td:hover {
background: var(--variableName);
}
And then bam, a solution that just requires some CSS and 2 JS functions!
Had some same problems, used addEventListener for events "mousenter", "mouseleave":
let DOMelement = document.querySelector('CSS selector for your HTML element');
// if you want to change e.g color:
let origColorStyle = DOMelement.style.color;
DOMelement.addEventListener("mouseenter", (event) => { event.target.style.color = "red" });
DOMelement.addEventListener("mouseleave", (event) => { event.target.style.color = origColorStyle })
Or something else for style when cursor is above the DOMelement.
DOMElement can be chosen by various ways.
I was researching about hover, to be able to implement them in the button label and make the hover effect
<button type="submit"
style=" background-color:cornflowerblue; padding:7px; border-radius:6px"
onmouseover="this.style.cssText ='background-color:#a8ff78; padding:7px; border-radius:6px;'"
onmouseout="this.style.cssText='background-color:cornflowerblue; padding:7px; border-radius:6px'"
#click="form1()">
Login
</button>
You can create a class in css
.hover:hover {
background: #ff0000;
}
and then add it dynamically
const columns = document.querySelectorAll('table td');
for (let i = 0; i < columns.length; i++) {
columns[i].classList.add('hover');
}
But your css and js files should be connected in index.html
const tds = document.querySelectorAll('td');
tds.forEach((td,index) => {
td.addEventListener("mouseover", ()=>hover(index))
td.addEventListener("mouseout", ()=>normal(index))
});
function hover(index){
tds[index].style.background="red";
}
function normal(index){
tds[index].style.background="yellow";
}
Try this code it will work fine .
If you use lightweight html ux lang, check here an example, write:
div root
.onmouseover = ev => {root.style.backgroundColor='red'}
.onmouseleave = ev => {root.style.backgroundColor='initial'}
The code above performes the css :hover metatag.

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