How to hide CSS background images that use !important - javascript

I'm trying to create a bookmarklet that will hide images on any page I'm currently viewing. It works for removing <img> tags and it creates a CSS style that tries to hide all background images. The issue I keep encountering are background images that are specified with !important. I can't figure out how to hide them.
Here is a codepen demonstrating the issue: http://codepen.io/Chevex/pen/kbDcv
If you remove the !important from the background image then it all works fine. Any ideas?

Make sure your CSS occurs after that CSS on the page and put the !important override on your CSS. Also, since you specify that you are using JavaScript, you can add your CSS as inline CSS on the actual element and use !important. The only thing that overrides inline important is user agent user important style sheets.[reference][example]

As others have pointed out, you can use the newer (IE9+) querySelectorAll function:
function hideImages() {
var d = document,s = window.getComputedStyle;
Array.prototype.forEach.call(
d.querySelectorAll("body *"),
function(el){
if (s(el).backgroundImage.match(/url/) ||
el.tagName === 'IMG'){
el.style.visibility="hidden";
}
}
);
}
$('button').click(hideImages);
http://codepen.io/anon/pen/rBnIx
Updated to include background-images set via CSS.
Though, you could probably lose a lot by turning anything with a background-image invisible. You might have better luck just turning that property off. You could either check the computed style of each element like above or just set them all like below. The function below uses setProperty to override !important which is also IE9+.
function hideImages() {
var a=document.querySelectorAll("body *"),i=a.length;
function _f(n){
if (n.tagName === 'IMG') n.style.visibility="hidden";
n.style.setProperty("background-image", "none", "important");
};
while(--i) _f(a[i]);
}
http://codepen.io/anon/pen/tnrdH

you can hide divs with backgrounds in the same manner as you do img tags in the linked code:
var imgs=document.querySelectorAll("div[style*='background']");
for (var i=0;i<imgs.length;i++) {
imgs[i].style.visibility="hidden";
}

Related

Javascript/AngularJS: Check if an element has the style overflow-y applied to it

I am trying to check inside my code if a has applied to its css styling the attribute overflow-y: auto. For example if my has a class "abcd", and "abcd" has for its css overflow-y: auto, then the passes. While I've already found a method for jquery, which I am not using, I want to find a method for pure javascript (or Angular JS) to find if the element has a given css attribute. How can I do this without jquery?
You can check with pure javascript by using this code : document.getElementById('myElement').style['overflow-y'].
The issue is that this code will works only for inline css style, as in <div style="overflow-y: visible">...</div>. If the css style comes from a class, you can't find it like this.
The jQuery css method will find the computed style (so it can detect the real value of overflow-y even if it comes from a class). But the css code is very huge. You can find it here : https://github.com/jquery/jquery/blob/master/src/css.js
I want to add that checking if an element has a specific css style is a very bad smell.
Instead of this, you should really consider to check if the element has a specific class. Or if you have using angularjs, a simple boolean in the model will do the trick.
If you really want to check if an element has the overflow-y: auto; style applied, according to the jQuery code, they use window.getComputedStyle(element). They also have a lot of code with a temporary div with a weird position (position:absolute;left:-11111px;width:60px;) but it is mostly to support old browsers like IE8 and IE9.
In your case, something like this could works : window.getComputedStyle(document.getElementById('myElement'))['overflow-y'] === 'auto'.
You can use the getComputedStyle method available on the window object.
var myElement = document.getElementById('myElement');
var overflowValue = getComputedStyle(MyElement).overflowY;
if (overflowValue == 'auto') {
// your code here
}
This method will get values of css properties applied in the moment.
For more info, you can refer here.
hope that helps.

jQuery add inline style on top of previous inline style for filters

I have an element that I want to add multiple inline filter styles on top of at different times.
The code I have now always resets the inline style so that whatever I set last is all that is there.
Here is an example snippet:
$("div").css("-webkit-filter","grayscale(1)");
$("div").css("-webkit-filter","blur(5px)");
.box{background:blue; width:100px; height:100px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box"></div>
You can see that i'm setting grayscale first and at that time it turns black. Then I set blur second, but it erases the grayscale filter and turns it back to blue then it blurs.
I want both grayscale and blur to be applied.
The issue is that you're overwriting the previous style since they both use the same property. Try putting them together in the same statement like so:
$("div").css("-webkit-filter","blur(5px) grayscale(1)");
EDIT: If you need to apply them at different times, try this:
$("div").css("-webkit-filter","grayscale(1)");
$("div").css("-webkit-filter","blur(5px) grayscale(1)");
This will set the grayscale first and then preserve it by reapplying it with the blur effect as well
This will take the current css and append the new stuff.
var $div = $("div");
$div.css($div.css() + "-webkit-filter","blur(5px)");
You may want to add both filters in one line, as you can see here:
https://developer.mozilla.org/en/docs/Web/CSS/filter
Jquery wants to overwrite the css if your setting the same property.
This question also addresses a similar problem, doesn't seem like a very clean solution though.
Don't overwrite css properties, but add to them with jQuery

JavaScript Cursor Change (and change back again)

I have this page that does some funky database stuff that takes a couple seconds to process, and in the meantime I'd like to set a "wait" cursor so the user doesn't flip out and keep clicking the button. I've looked at the
document.body.style.cursor = "wait"
thing, the problem with this is that it only works when the mouse is over the body of the page (i.e. still shows normal pointer if it's over a button). How can I set it so that no matter where the mouse is on the page, it shows a wait icon?
A second part to this question is, once it's done it's thing, how do I set it back? If I set it back to "default", this seems to override any "hover" cursor changes I had set in my CSS (so it no longer becomes a hand when over a specified object, etc.).
EDIT: the first answer works nicely, except in IE it doesn't refresh the cursor (so you notice the change of cursor type) until you actually move the cursor. Any fixes?
What I suggest is two things:
a) Better write a CSS like
body.waiting * { cursor: wait; }
b) Use the JS to handle the body class
/* when you need to wait */
document.body.className = 'waiting';
/* to remove the wait state */
document.body.className = ''; // could be empty or whatever you want
You might want to add the class instead of replace the whole class attribute, what I suggest is to use something like jQuery for that.
EDIT 2019: don't use jQuery for just this, use classList
The styling should be handled via CSS, as stated by W3C.com:
CSS is the language for describing the presentation of Web pages, including colors, layout, and fonts. ... The separation of HTML from CSS makes it easier to maintain sites, share style sheets across pages, and tailor pages to different environments. This is referred to as the separation of structure (or: content) from presentation.
As suggested by Tom Rogerro, add a line to your CSS file:
body.waiting * { cursor: wait; }
However, your script should not overwrite the entire list of class names. Tom suggested setting the class names via jQuery, but jQuery is unnecessary in this case. Simple Javascript can do this.
To add a class name 'waiting' to the document body:
document.body.classList.add('waiting');
To remove a class name 'waiting' from the document body:
document.body.classList.remove('waiting');
For your first problem, try using cursor: wait !important;.
For your second problem, the default cursor for elements is cursor: auto;, not cursor: default; or cursor: inherit;.
If you are happy using JQuery then a quick way to solve this would be to use:
$('*').css('cursor','wait')
I don't know how elegant this is but it has been working for me,
Not an answer to the question, but a way of achieving what is wanted.
Make a div (see class below) visible when you are loading.
ensures no element is accessible and dimmed display indicates this.
you can add an animated gif to indicate something is going on instead of the cursor.
.loading{
position:fixed;
height:100%;
width:100%;
left:0;
top:0;
cursor:wait;
background:#000;
opacity:.5;
z-index:999}
Any elements that don't inherit the cursor by default (such as buttons) will need to set the cursor to inherit:
someButton.style.cursor = 'inherit';
To go back to the default for an element (and not break things like :hover with a forced cursor), set it to an empty string:
document.body.style.cursor = '';
I tried everything but finally this jquery worked, especially if you want wait cursor over all elements including buttons and links.
define at the top of angular .ts file
declare var $: any;
and then where ever you want wait cursor:
$('*').css('cursor','wait');
and remove wait:
$('*').css('cursor','auto');
To fully replace the CSS toggling behaviour, we can simply use this inline:
<img
src=https://cdn.sstatic.net/Img/unified/sprites.svg
onmouseover="this.style.cursor = 'crosshair'"
>

Javascript won't overwrite CSS display property

I have a DIV that is set do display:none from CSS and it's supposed to be made visible (style.display = '';) at some point by javascript.
The problem is that if I put the display:none in the CSS file the javascript does not seem to have any effect. I have also tried changing the background color instead of the display property, and that works.
I have the code running here (just press the edit link).
I really thank you for taking the time to look into this.
Set it to block or inline using Javascript.
Writing style.display = "" will clear any display set in the inline style, and cause it to revert to whatever it inherited from CSS.
Alternatively, you can change the element's className using Javascript so that the CSS rule no longer applies.
This is because style.display = '' only affects inline styles on an element. It doesn't change the style sheet.
You should set it to whatever display you need:
style.display = 'block';
or add a class that represents the style you want.
other way to hide content is use opacity=0 and to again make visible use opacity=1 thats it....!!!

Quickly repaint array of unicode symbols in JavaScript

I want to change background/foreground color of many symbols with the same CSS class. Right now I'm doing it with jQuery — like $('back_COLORED').css('background-color', '#00FF00'), but this approach is slow when there are many elements with such class (>900).
Seems it's because jQuery don't change CSS rules itself, but finds all elements one-by-one and applies inline styles to them. At least, this is what I see in inspector. So, the question is:
How can I change the CSS rules itself?
Will it be much faster?
Can I make it cross-browser (IE6 doesn't count)?
UPD: I'm trying to make some kind of color scheme editor. The source is at http://github.com/kurokikaze/cinnabar/. Don't mind PHP things, editor is fully client-side (with just some libraries fetched from the net).
UPD2: Tried canvas approach, still slow. Canvas branch is at http://github.com/kurokikaze/cinnabar/tree/canvas.
The most cross-browser friendly way to override a class definition is to write a new rule and add it to the end of the last stylesheet in the document. You can edit an existing style rule, but even some recent browsers can make it difficult.
function newRule(selector, csstext){
var SS= document.styleSheets, S= SS[SS.length-1];
// this example assumes at least one style or link element
if(S.rules){
S.addRule(selector,csstext,S.rules.length);
}
else if(S.cssRules){
S.insertRule(selector+'{'+csstext+'}'),S.cssRules.length)
}
}
newRule('.someclass','background-color:#0f0');
You can add as many 'property:value;' bits in the csstext as you need.
Remember to prefix a '.' to a class name or a '#' to an id,
and the css must be written as a style rule (with-hyphens, not camelCase).
Of course, it will not override inline styles, and it is overkill for small, local changes.
It also may make the redrawing of the page more obvious than changing one element at a time,
but it may be just what you need here.
There are different ways depending on which browser you are dealing with. This is documented on Quirks Mode.
Some libraries provide an abstraction layer, such as YUI's StyleSheet utility.
There should be a significant performance boost since you aren't using JS/DOM to cycle through all the elements.
Another approach would be to predefine your styles:
body.foo .myElements { … }
And then edit document.body.className
If you can select the parent div by id, maybe you could select by tag inside it? Or are there elements of the same kind that should change color and that should not, inside the parent?
It would be nice to have an idea of what you're building here. 900+ objects seems to be a lot... maybe a completely different approach could be used? Canvas, SVG?
Try hiding the items you want to change before changing them, make the change and then display them again. This is common practice to speed up things as you minimize the repaint events in the viewport. In this case when you only setting one css property it might not be that of a benefit but it´s worth a try I say.
Try:
$('back_COLORED').hide();
$('back_COLORED').css('background-color', '#00FF00');
$('back_COLORED').show();
or
$('back_COLORED').hide().css('background-color', '#00FF00').show();
I would stick in trying changing a CSS property, instead of parsing the DOM.It is about the CSS engine vs. DOM+JS here, and the winner is clear.
It happens I just uploaded a tiny library that replaces CSS by Javascript: jstyle
This is may be an overkill, but you will find in the source code of jstyle.js all the code you need to update cross browser the CSS properties of your page.
I think a better solution would be to write a more specific CSS rule (that would override the normal colour) that can be activated by simply changing one element's css class.
So for example if you had the following structural markup:
<div id="container">
<span class="colored">Test 1</span>
<span class="colored">Test 2</span>
</div>
And CSS:-
.colored { background-color: red; }
.newcolor .colored { background-color: blue; }
Then in your jquery you add the .newcolor class to the container div:-
$('#container').addClass('.newcolor');
When you do that the second CSS rule will override the first because it is more specific.
Inject the css code into a style tag:
var style = $('style').attr({
type:"text/css",
media:"screen",
id:'changeStyle'
}).html('.tempClass { color:red } .tempClass p { background:blue }').prependTo('body');
and on every changes on your color with color picker you only rewrite the html inside of #changeStyle tag.
Have no idea if it works (didn't tested) but you should give a try.
This is jQuery pluggin for work with css rules: http://flesler.blogspot.com/2007/11/jqueryrule.html
not sure about its performance, but worth a try.

Categories

Resources