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.

Answers:

Answer

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?

Answer

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.

Answer

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

Answer

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();
Answer

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.

Answer

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.

Answer

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.

Answer

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.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.