JavaScript cssText not working as expected in Firefox and Opera browsers - javascript

Please consider the code snippet below:
<!DOCTYPE html>
<html>
<body>
<div id="mydiv">Sample Text</div>
<script type="text/javascript">
var md=document.getElementById("mydiv");
md.style.cssText="background-color:yellow !important;color:red;font-size:70px;font-weight:bold;";
setTimeout(function(){
md.style.backgroundColor="blue";
md.innerHTML+="<br/>Updated!";
},2000);
</script>
</body>
</html>
Explanation: I am trying out the cssText browser support and noticed that cssText is not working as per my expectation in Firefox, Opera browsers.
The above code defines "background-color:yellow !important" and after 2 seconds the background-color is changed to blue. But since I have specified '!important' in my cssText, I assume the background-color should not get updated. This works in IE, Chrome, Safari. But not in Firefox, Opera.
Can someone please suggest.
EDIT: I want to specify the !important rule for a css property and restrict further changes to it via javascript. I would like to achieve this using JavaScript i.e. specifying !important via JavaScript. Any help on this would be appreciated.

Stumbled across this question while googling for something else.
The first thing to understand, is that cssText doesn't create another style: It is merely a shorthand that lets you assign multiple styles at once. The following are roughly identical:
element.style.cssText = "background-color:yellow;color:red;";
element.style.backgroundColor = "yellow";
element.style.color = "red";
The only real thing to note, is that I believe that assigning to cssText will overwrite any existing element styles. Eg, the following will result in a style that is exactly equal to color:red; and not equal to background-color:yellow;color:red;. cssText effectively removes any existing element styles before applying the ones specified:
element.style.backgroundColor = "yellow";
element.style.cssText = "color:red;";
The second thing to realize, is that !important doesn't make a style read-only. It only prevents defined styles of higher specificities being used, and only does so as long as it is defined. When you assign the background color value of blue, you are effectively removing !important from the declaration. You'd have to set your background color as background-color:blue !important; in order to keep it.
In short, if something overwrites your background-color:yellow !important; with background-color:blue;, there's nothing you can do about it. Unless you do some other fancy work, like creating a timer interval that every X milliseconds resets the yellow !important style. But then you run into problems of having to keep track of the interval, especially if you may actually want to set the background color to some other value, otherwise it will just get overwritten on you!
var element = ...;
setInterval(1000, function(){
if (element.style.backgroundColor != "yellow !important") {
element.style.backgroundColor = "yellow !important";
}
});
The one thing I can think of, is if these styles are set in stone, you could just make them actual rules instead of inline element styles. You can keep the !important tag if you make it a rule:
.bg-yellow {
background-color: yellow !important;
}
element.className = "bg-yellow";

Here is your JS modified code. I've checked in FF 27 and it is working.
var md=document.getElementById("mydiv");
md.style.cssText="background-color:yellow !important;color:red;font-size:70px;font-weight:bold;";
setTimeout(function(){
md.style.setProperty="background-Color:blue"; //modified this line
md.innerHTML+="<br/>Updated!";
},2000);
Here is the Working Demo for you.
http://jsbin.com/kifozeka/2/edit

Related

How to change background color of a page while avoiding iframes/images/videos using js/css?

I am new to CSS/JS and I am creating an accessibility chrome extension and I need to change the background color of the page. The problem I encounter is when changing the color of pages that have videos like twitch and youtube.
function changeBKColorPredefined(background, color) {
var tags = document.querySelectorAll("*");
for (let i = 0; i < tags.length; i++) {
tags[i].style.backgroundColor = background;
tags[i].style.color = color;
}
}
This code clearly changes everything there is on the page, but I don't know how to avoid changing the background color of certain tags without having to specifying them which would of course become a really hard to maintain code.
Example output of the code showed before:
I have also tried to only change the body color by using document.body.style.backgroundColor but it does not change the color of the whole page.
Thank you for any help.
Edit: an example of what I mean can be found in this extension: https://chrome.google.com/webstore/detail/a%20-fontsize-changer/ckihgechpahhpompcinglebkgcdgpkil
Use css custom properties also known as CSS Variables. This way you can set in your CSS property value as background, and then change only said value.
Simple example would be:
:root {
/**
* This will be your default value. In this example - black.
*/
--changing-background: #000;
}
/**
* In places where you want to change backround set it as background color
*/
.classes-with-changing-background {
background-color: var(--changing-background);
}
Then in JS you do:
// This is your JS. In my example we change property value to white
document.documentElement.style.setProperty('--changing-background', '#fff');
I took JS from this answer

Why does Firefox fire a mouseenter event on page load?

When hovering over an element and then refreshing the page (without moving the mouse):
Chrome does not fire the mouseenter event on page load
Firefox does fire the mouseenter event on page load
Below is an example snippet. To reproduce the issue, hover over the div and then refresh the page. In Chrome, the div does not contain "mouseenter". In Firefox, it does.
Note that this does not work in the Stacksnippets environment since you need to click "run snippet" first. JSFiddle: https://jsfiddle.net/9fu6cx5d/7/
let div = document.getElementById('my-div');
div.addEventListener('mouseenter', function () {
div.innerHTML = 'mouseenter';
});
#my-div {
width: 150px;
height: 150px;
background-color: #aaaaaa;
}
<div id="my-div">
</div>
Which browser has the correct behaviour? How can I work around the difference in behaviour or at least make them both behave the same?
Chrome version: 59.0.3071.115 (Official Build) (64-bit)
Firefox version: 54.0 (64-bit)
As pointed out in the comments, Chrome's behavior is the correct one according to the specs. Below is an idea on how to work around the difference.
You can make sure you get the value right by checking whether the mouse is inside the bounds of the div on document load. Unfortunately there is no way in JS to check the mouse position without firing events, so you will have to resort to some hack involving CSS hover rules and checking against them on $(document).ready.
To quote this hilarious answer:
Overlay your page with a div that covers the whole document. Inside
that, create (say) 2,000 x 2,000 elements (so that the :hover
pseudo-class will work in IE 6, see), each 1 pixel in size. Create a
CSS :hover rule for those elements that changes a property (let's
say font-family). In your load handler, cycle through each of the 4
million elements, checking currentStyle / getComputedStyle() until
you find the one with the hover font. Extrapolate back from this
element to get the co-ordinates within the document.
N.B. DON'T DO THIS.
While you definitely shouldn't do this, the general idea of using non-effective hover styles for the sake of checking if an element is hovered without needing JS events is a good one if you just need to work around browser quirks. I'm using font-weight in the example below, but you can change it to whatever works for you.
The css
#my-div:hover {font-weight:700;}
The js
// Pseudocode!
var mouseIsInside = false,
div = $('#my-div');
$(document).ready(function(){
if (div.css('font-weight') === 700) {
mouseIsInside = true;
}
doStuffIfMouseInside();
});
div.on('mouseenter', function(){
mouseIsInside = true;
doStuffIfMouseInside();
})
function doStuffIfMouseInside() {
if (mouseIsInside) {
...
}
}
If you add (function(){})(); around your code it seems to work in both browsers.
It seems that firefox might be firing events before the dom is available causing problems with mousein/out events.
See: https://jsfiddle.net/9fu6cx5d/8/

use setattribute to change color (in chat)

I want to change the chat window fontcolor/fontsize of the page younow. I tried 2 'cssText' samples but I'm unable to change the font color to RED. How can I change the chat window font color to RED? I'm using Firefox and greasemonkey.
sample 1:
document.getElementById("chatcomments").style.cssText = 'font-size: 36px; color: red !important;'
sample 2:
document.querySelector(".chatcomments span").style.cssText = 'font-size: 36px; color: red !important;'
click to see the chatimage
you need to be specific with the attributes of the style object:
document.getElementById("chatcomments").style.color = "red";
document.getElementById("chatcomments").style.fontSize = "30px";
If you use JQuery, you can use the css function, like so:
$(".chatcomments > span").css("color", "red");
You do not need to set font-size again if it already has been set. Another issue is that .chatcomments span won't work as they're two different things; instead, > will work: .chatcomments > span.
It is also better to use RGB or hexadecimal values instead of colour names, for example:
$(".chatcomments > span").css("color", "#EE4B38"); //RGB
$(".chatcomments > span").css("color", "rgb(238, 75, 56)"); //Hex
In the case that you're trying to create a custom client-side script in Tampermonkey or Greasemonkey (it looks like you are), you must use // #require to import the JQuery source (as seen in this answer):
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js
el.style.setProperty('color', 'red'); seems more right

JavaScript MutationObserver calling on itself recursively

I am trying to use MutationObserver to Observe for style attribute changes in body element and change the overflow property of the style attribute of body to scroll.The style attribute changes when i make the browser window smaller .Firefox ends up crashing saying unresponsive script.Can anyone point out what wrong am i doing here.It seems to work properly in chrome though.
My code:
var target=document.body;
var Observer=new MutationObserver(function(mutations) {
mutations.forEach(function(mutationRecord){
document.body.style.overflow="auto";
});
});
Observer.observe(target,{attributes:true,attributeFilter:['style']});
I'd look to solve this at the root level: Why do different parts of your code want to fight over the document.body.style.overflow property?
But answering the mutation observer question:
If your goal is to ensure that document.body.style.overflow is set to "auto" regardless of changes made to it elsewhere, I'd only change it if it's not the value you want:
var Observer=new MutationObserver(function(mutations) {
if (document.body.style.overflow != "auto") {
document.body.style.overflow = "auto"
}
});
Observer.observe(document.body,{attributes:true,attributeFilter:['style']});
Also note that there's no need for the forEach loop.
At a guess, I'd say Firefox is firing the mutation observer even when the property hasn't actually changed, but Chrome isn't.
Side note: Again I'd say it would be better to find and deal with the fact your code seems to be fighting with itself. But as an alternative to a mutation observer workaround, here's a CSS workaround: An !important rule in a stylesheet overrides a normal inline style. So
body {
overflow: auto !important;
}
Now, that won't override document.body.style.overflow = "none !important", but it'll override any non-important rule, even an inline style one.
Your problem is on line:
document.body.style.overflow="auto";
Basically it creates an infinite loop which could surpass the Browser Javascript Stack size limit.
With your code you are observing the body dom, and when a change is made in body dom you actually change it style again, this goes forever.

Why are style assignments performed immediately after creation not animated?

Opening this fiddle on Webkit will show what I'm talking about.
How can I specify an element's style when it is first specified, and then its final state?
It should be possible to specify a single step animation fully this way (without having to start using #keyframes) but it seems like there is a lot of implementation specific strangeness I must deal with at this point. Note how in Firefox no animation is performed...
Seems to be the same issue as described here: CSS3 transitions to dynamically created elements
so
$("#one").on('click',function(){
var word = $("<div style='opacity: 0; height:0'>word</div>");
$('body').prepend(word);
window.getComputedStyle(word[0]).getPropertyValue("top");
word.css({height: 100, opacity: 1});
});
also works in this case: http://jsfiddle.net/wWnnH/3/
Alternatively, you can use jQuery.animate()
word.animate({height: 100, opacity: 1}, 5000);
Will work without the CSS, and on both webkit and mozilla. Although this defeats the purpose of trying to use CSS3 I guess.

Categories

Resources