CSS :hover selector doesn't work after dynamic changes - javascript

I am making a chrome extension that changes element background color, but after changing
the:hover selector doesn't work anymore.
I saw this question but in my case, I can't change the CSS rule to !important
is it possible to programmatically change element style without override:hover rules?
For example:
var div = document.querySelector("div");
div.onclick= function(){
div.style.background="red";
//after doing that the hover is not working anymore
}
div{
height:100px;
width:100px;
background:green;
}
div:hover{
background:blue;
}
<div>
I want the background to be red but to still have the blue on :hover.

We can use javascript mouse hover and mouse out like below
$("#id").mousehover
$(document).ready(function(){
$("p").mouseover(function(){
$("p").css("background-color", "red");
})
$("p").mouseout(function(){
$("p").css("background-color", "");
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<p> Change Background </p>

If you can't use !important you can get the :hover styles via document.styleSheets and use them with Javascript events:
function getElementHoverCssText(element){
var elementHoverCssText = "";
var docstyle = document.styleSheets;
var eltagregex= new RegExp(""+element.tagName+":hover","gi");
var idregex= new RegExp("#"+element.id+":hover","gi");
for(i = 0; i < docstyle.length; ++i){
for(j = 0; j < docstyle[i].cssRules.length; ++j){
if(eltagregex.test(docstyle[i].cssRules[j].selectorText)){
elementHoverCssText+=docstyle[i].cssRules[j].style.cssText;
}
element.classList.forEach(classn =>function(){
if((new RegExp("."+classn+":hover","gi")).test(docstyle[i].cssRules[j].selectorText)){
elementHoverCssText+=docstyle[i].cssRules[j].style.cssText;
}
});
if(idregex.test(docstyle[i].cssRules[j].selectorText)){
elementHoverCssText+=docstyle[i].cssRules[j].style.cssText;
}
}
}
return elementHoverCssText;
}
var originalCSSText = element.style.cssText;
function changeColor(el){
//el.style.backgroundColor="red"; uncomment for make the button red immediately after click
el.innerHTML="mouse out to see color change."
originalCSSText+="background-color: red;";
}
element.addEventListener("mouseover",function(){
originalCSSText=element.style.cssText;
element.style.cssText+=getElementHoverCssText(element);
});
element.addEventListener("mouseout",function(){
element.style.cssText=originalCSSText;
});
#element{
height:100px;
width:200px;
background-color:green;
}
#element:hover{
background-color:blue;
}
<div id="element" onclick="changeColor(this)">click to change color to red and still have hover</div>

Related

Apply Css Animation to a class with onclick Using JavaScript

I have a this script :
function ani(){
document.getElementById('para').className ='exeInputapparition';
}
To apply a css animation on my element who has the ID para.
It's working but i wanted to know if it's possible to apply to all element who have the class para instead of the ID because i have more than one element where i need to apply my CSS animation.
Thanks in Advance for your help :)
The Css :
#keyframes inputapparition {
0%
{
opacity: 0;
}
100%
{
opacity: 1;
}
}
.exeInputapparition
{
animation-name: inputapparition;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
#para
{
margin: 0;
font-family: "Roboto"
font-size: 20px;
opacity: 0;
}
The function querySelectorAll returns all elements, it's a "DOM array", therefore there isn't the attribute className. You should loop the list and change one by one:
var allElementsPara = document.querySelectorAll(".para");
for (var i = allElementsPara.length - 1; i >= 0; i--) {
allElementsPara.item(i).classList.add("exeInputapparition");
};
You can use document.querySelectorAll
var x=document.querySelectorAll(".para");
for(var a =0;a<x.length;a++){
x[a].classList.add("exeInputapparition")
}
JSFIDDLE
JSFIDDLE WITH .para
The id is unique. You must use a same class for all element that you want to animate. For all element, put the class animate and edit the function
function ani(){
document.getElementsByClassName('animate').className ='exeInputapparition';
}
A more performing solution would be to apply the class to the body element.
Every access to the DOM takes some ms and when your web page becomes huge, with a lot of JavaScript, it can get slow.
Accessing a single DOM element (<body>) instead N elements with the given class will:
reduce the number of accesses to the DOM;
reduce to 0 the queries you perform on the DOM;
make sure all the elements starts appearing at the same time;
assure that every element with the class para added after the script has run, will have the correct style;
// here I use a `setTimeout` to make the function start automatically
// logically you can take the content of this function and put it
// wherever you prefer
setTimeout(function() {
document.body.className += ' in';
}, 1000);
.para {
opacity: 0;
transition: opacity 0.5s linear;
}
.in .para {
opacity: 1;
}
<div class="para">para 1</div>
<div class="para">para 2</div>
<div class="para">para 3</div>
You can disregard the previous answers, people did and could not know what exactly you want before you posted the css.
You do not the keyframes for this.
Here is a full JS solution, as you need JS for this anyway.
document.querySelector(".reveal3").addEventListener("click", function(){
toggle();
});
function toggle(){
var c = document.querySelector(".reveal3");
if(c.style.opacity == 1){
c.style.opacity = 0;
} else {
c.style.right = "0px";
c.style.opacity = 1;
}
}
See it in action here, the div on the right side, click on it to toggle visibility.
http://codepen.io/damianocel/pen/GopoJB
this solution will help your.it is easy to use jquery with this.I have implemented for a div.you can use it for image also.so try this
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
</head>
<body>
<div class="clickme" style="background-color:orange;width:100px;height:100px;">
<!--use <img src="imageurl"/> here-->
</div>
<!-- js-->
<script type="text/javascript">
$(document).ready(function(){
$(".clickme").click(function(){
$(this).animate({opacity:0.5},1000);
});
});
</script>
</body>
</html>

How to show div with slide down effect only with javascript

I Want to show div on click with slideup effect using javascript(not jquery).
Here is my HTML code:-
<div class="title-box">show text</div>
<div class="box"><span class="activity-title">our regions bla bla</span></div>
Kindly advise me asap.
The question states that the solution needs to be done with pure JavaScript as opposed to jQuery, but it does not preclude the use of CSS. I would argue that CSS is the best approach because the slide effect is presentational.
See http://jsfiddle.net/L9s13nhf/
<html><head>
<style type="text/css">
#d {
height: 100px;
width: 100px;
border: 1px solid red;
margin-top: -200px;
transition: margin-top 2s;
}
#d.shown {
margin-top: 100px;
}
</style>
</head>
<body>
<button id="b">Toggle slide</button>
<div id="d">Weeeeeeee</div>
<script type="text/javascript">
var b = document.getElementById('b');
var d = document.getElementById('d');
b.addEventListener('click', function() {
d.classList.toggle('shown');
});
</script>
</body></html>
The basic algorithm is to add a class to the element you want to slide in/out whenever some button or link is clicked (I'd also argue that a button is more semantically appropriate here than an anchor tag which is more for linking web pages).
The CSS kicks in automatically and updates the margin-top of the sliding element to be visible on-screen. The transition property of the element tells the browser to animate the margin-top property for two seconds.
You can try below code:
Working Demo
document.getElementById('bar').onclick = (function()
{
var that, interval, step = 20,
id = document.getElementById('foo'),
handler = function()
{
that = that || this;
that.onclick = null;
id = document.getElementById('foo');
interval =setInterval (function()
{
id.style.top = (parseInt(id.style.top, 10) + step)+ 'px';
if (id.style.top === '0px' || id.style.top === '400px')
{
that.onclick = handler;
clearInterval(interval);
if (id.style.top === '400px')
{
id.style.display = 'none';
}
step *= -1;
}
else
{
id.style.display = 'block';
}
},100);
};
return handler;
}());
You can refer following below:
<div class="title-box">
show text
</div>
<div class="box" id="slidedown_demo" style="width:100px; height:80px; background:#ccc; text-align:center;">
<span class="activity-title">our regions bla bla</span>
</div>

Change style for array of DIVS

I have 100 DIVS in an array called 'lights', appended to the page with a unique ID. Some of those DIVS are also in another array called 'frozen'.
How can I change the background color of the DIVS in 'lights' but not the divs in the 'frozen' array?
For example, to change all of the divs I would use:
for(var l=0;l<LIGHTS_NUMOF;l++){
$("#light"+l).css("background-color", "#ff0000");
}
Generating the array:
var LIGHTS_NUMOF = 100;
var lights = [];
for(var l=0;l<LIGHTS_NUMOF;l++){
var newLight = $("<div class=\"light\" id=\"light"+l+"\"></div>");
$(".lights").append(newLight);
lights.push(newLight);
}
However, this obviously changes ALL of the divs.
How do I avoid changing the DIVS which are in the 'frozen' array?
Ideally I would like to express lights.backgroundcolor = 'red' where DIV isn't 'frozen'.
Adding DIV to 'frozen':
$( ".light" ).click(function() {
frozen.push(this);
});
If you are actually looking at items in the DOM, you can easily do what you want using jQuery.not() like the following example.
$(document).ready(function() {
$("#changeLights").on("click", function() {
$(".lights").not(".frozen").addClass("frozen");
});
});
div {
height : 50px;
width : 50px;
background-color : #CCC;
margin: 5px;
float: left;
}
.frozen {
background-color : #F00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="lights"></div>
<div class="lights"></div>
<div class="lights frozen"></div>
<div class="lights"></div>
<div class="lights frozen"></div>
<div class="lights frozen"></div>
<input id="changeLights" type="button" value="Change" />
Try this:
for(var l=0;l<LIGHTS_NUMOF;l++){
if(frozenArray.indexOf(lightsArray[l]) == -1){ // if id is not in frozen array
$("#light"+l).css("background-color", "#ff0000");
}
}
First of all...
Try modify this part of your code
$(".light").click(function() {
$(this).addClass("frozen");
});
Then to get all of that is not frozen, do this:
$(".light").not(".frozen").css("background-color", "#ff0000");

prevent scrolling of overflow:hidden elements when link to anchors are clicked

clicking the link the anchor is reached, but even if the parent element has overflow:hidden
it scrolls unnecessarily hiding the contents
<style>
div#x
{overflow:hidden;border-bottom:1px red solid;}
div#x > div
{border:1px red solid;padding:10px;float:left;width:33%;box-sizing:border-box;padding-bottom:10000px;margin-bottom:-10000px;}
</style>
<div id="x">
<div>go to<br><br>a</div>
<div>a<br><br><br><br>a</div>
<div>a<br><br><br><br><br><br><span id="test">go here</span></div>
</div>
demo: http://jsfiddle.net/aj8cX/5/
is there a way to fix this behavior?
This is as close as I could get, using table > table-cell:
http://jsfiddle.net/mikedidthis/AmNxf/
Would work well for static content, but for dynamic content it may cause some issues.
You could use some javascript trickery.
I am using jQuery, but you can use anything you want.
$('a[href="#test"]').on('click', function(){
var test_element = $('#test');
var scroll_top = test_element.scrollTop();
var max_height = test_element.parent().height();
if (scroll_top < max_height) { return false; }
else { return true; } //only scroll if the item is in view
});
You can use javascript to get elements of equal height:
var height = 0;
$.each($('#x div'),function(k,v){
if($(this).height() > height){
height = $(this).height();
}
});
$.each($('#x div'),function(){
$(this).height(height);
});
Fix your css like so:
div#x
{
overflow:visible;
height:10000px;
}
div#x div
{
border:1px red solid;
float:left;
width:33%;
box-sizing:border-box;
margin-right:-1px;
}
Working example: http://jsfiddle.net/aj8cX/6/

How change content value of pseudo :before element by Javascript [duplicate]

This question already has answers here:
Selecting and manipulating CSS pseudo-elements such as ::before and ::after using javascript (or jQuery)
(26 answers)
Closed 2 years ago.
I have the grap constructured by CSS, which is dynamically changes by JS. I show graph max value by pseudo element as:
.graph:before {
content:""; //value that want set by JS
position:absolute;
top:0;
left:0;
}
That's why I need to set this value by JS. I tried $(".graph:before").css("content", hh); but it didn't help. How to get that value?
I hope the below snippet might help, you can specify the content value you want via JS using the CSS attr() function.
Below you have two options: to use JavaScript or jQuery:
jQuery:
$('.graph').on('click', function () {
//do something with the callback
$(this).attr('data-before','anything'); //anything is the 'content' value
});
JavaScript:
var graphElem = document.querySelector('.graph');
graphElem.addEventListener('click', function (event) {
event.target.setAttribute('data-before', 'anything');
});
CSS:
.graph:before {
content: attr(data-before); /* value that that refers to CSS 'content' */
position:absolute;
top: 0;
left: 0;
}
Update (2018): as has been noted in the comments, you now can do this.
You can't modify pseudo elements through JavaScript since they are not part of the DOM. Your best bet is to define another class in your CSS with the styles you require and then add that to the element. Since that doesn't seem to be possible from your question, perhaps you need to look at using a real DOM element instead of a pseudo one.
You can use CSS variable
:root {
--h: 100px;
}
.elem:after {
top: var(--h);
}
let y = 10;
document.documentElement.style.setProperty('--h', y + 'px')
https://codepen.io/Gorbulin/pen/odVQVL
I believe there is a simple solution using the attr() function to specify the content of the pseudo element. Here is a working example using the 'title' attribute, but it should work also with custom attributes.:
document.getElementById('btn_change1').addEventListener("click", function(){
document.getElementById('test_div').title='Status 1';
});
document.getElementById('btn_change2').addEventListener("click", function(){
document.getElementById('test_div').title='Status 2';
});
#test_div {
margin: 4em;
padding:2em;
background: blue;
color: yellow;
}
#test_div:after {
content:attr(title);
background: red;
padding:1em;
}
<button id='btn_change1'>Change div:after to [Status 1]</button>
<button id='btn_change2'>Change div:after to [Status 2]</button>
<div id='test_div' title='Initial Status'>The element to modify</div>
People who are still looking some solution of same problem, it is doable as follows using jQuery:
<button id="changeBefore">Change</button>
<script>
var newValue = '22';//coming from somewhere
var add = '<style>.graph:before{content:"'+newValue+'"!important;}</style>';
$('#changeBefore').click(function(){
$('body').append(add);
});
</script>
This example illustrate that on clicking button: changeBefore , the value for .graph:before will change as per new dynamic coming value for it.
For more description about changing of :before or :after element style or getting its content:
Lets suppose your HTML is like this:
<div id="something">Test</div>
And then you are setting its :before in CSS and designing it like:
#something:before{
content:"1st";
font-size:20px;
color:red;
}
#something{
content:'1st';
}
Please notice I also set content attribute in element itself so that you can take it out easily later.
Now there is a button clicking on which, you want to change the color of :before to green and its font-size to 30px. You can achieve that as follows:
Define a css with your required style on some class .activeS :
.activeS:before{
color:green !important;
font-size:30px !important;
}
Now you can change :before style by adding the class to your :before element as follows:
<button id="changeBefore">Change</button>
<script>
$('#changeBefore').click(function(){
$('#something').addClass('activeS');
});
</script>
If you just want to get content of :before, it can be done as:
<button id="getContent">Get Content</button>
<script>
$('#getContent').click(function(){
console.log($('#something').css('content'));//will print '1st'
});
</script>
I hope it helps
I had a similar problem, but with icons. I needed to switch the play and pause icons for an audio player in html5.
The problem here was that HTML, CSS and jQuery all interpret differently the "content" values to show icons, due to the use of \ symbol.
So the best workaround is to delete and re-create the node. Here's my code:
<ul class="list list--buttons">
<li><i class="fa fa-step-backward"></i></li>
<li><i class="fa fa-play"></i></li>
<li><i class="fa fa-step-forward"></i></li>
</ul>
And the script
<script type="text/javascript">
$(
function(){
var aud = $('audio')[0];
$('.playpause').on('click', function(e){
e.preventDefault();
if (aud.paused) {
aud.play();
/* from play icon to pause icon */
$('.playpause .fa-play').remove();
$('.playpause').append('<i class="fa fa-pause"></i>');
}
else {
aud.pause();
/* from play icon to pause icon */
$('.playpause .fa-pause').remove();
$('.playpause').append('<i class="fa fa-play"></i>');
}
})
$('.next').on('click', function(e){
e.preventDefault();
aud.src = '{$content:audio-file}';
})
$('.previuos').on('click', function(e){
e.preventDefault();
aud.src = '{$content:audio-file}';
})
aud.ontimeupdate = function(){
$('.progress').css('width', aud.currentTime / aud.duration * 100 + '%')
}
})
</script>
Hope it helps!
You can use document.styleSheets to modify pseudo selector cssRules
document.styleSheets[0].cssRules[0].style.content = '"111"';
If you use something like an onoffswitch and want to translate the css content attribute with i18next then you can use one of the i18next Framework example from github (i18next Jquery Framework) and then you extended the function with this code:
var before = i18next.t('onoffswitch.before');
var after = i18next.t('onoffswitch.after');
$('.onoffswitch-inner')
.attr('data-before', before )
.attr('data-after', after );
and the css code must be this:
.onoffswitch-inner:before {
content: attr(data-before);
padding-left: 10px;
background-color: #65AFF5; color: #FFFFFF;
}
.onoffswitch-inner:after {
content: attr(data-after);
padding-right: 10px;
background-color: #EEEEEE; color: #999999;
text-align: right;
}

Categories

Resources