jquery: create/read .css styles at runtime - javascript

I have an application where I'm using jQuery + maphilight
, and in addition to the highlighting of image map segments, I would like to highlight certain HTML elements dynamically, based on mouseover/mouseout events for the image maps.
I know how to do all of it (just the appropriate calls to addClass and removeClass for the HTML element that I want to highlight) except for one thing. I want to do either of the following:
create a CSS style at runtime that mirrors the maphilight visual settings (line/fill style + opacity)
set the maphilight plugin to mirror a CSS style that I have set up.
I'd prefer to do the latter and configure it in a .css file, but at present I don't know how do to either.
Can anyone help me?
edit: I'm looking for an answer that includes how to read or write styles from the jQuery maphilight plugin, since it doesn't have much documentation.

It may only change header style sheets. This technique is superior when used correctly. It should never replace a proper class assignment.
var renderDropArea = function(renderMe) {
var dropSheet = document.getElementById('dropAllowedDisplay');
if (renderMe) {
// IE 7 & 8
if (dropSheet.styleSheet) {
dropSheet.styleSheet.addRule('.dropAllowedHead','background-color:#72F193;');
dropSheet.styleSheet.addRule('.dropAllowed','background-color:#72F193;');
} else {
document.getElementById('dropAllowedDisplay').innerHTML =
".dropAllowedHead { background-color:#72F193; } .dropAllowed { background-color:#72F193; }";
}
} else {
// IE 7 & 8
if (dropSheet.styleSheet) {
if (dropSheet.styleSheet.rules.length) {
dropSheet.styleSheet.removeRule(0);
dropSheet.styleSheet.removeRule(0);
}
} else {
document.getElementById('dropAllowedDisplay').innerHTML = '';
}
}
}

Related

CSS by data-attribute will not refresh/repaint

In a HTML5/JS application we have a view with some styles depending on the data-attribute of elements:
like
<li data-level="0"></li>
or
<li data-level="1"></li>
CSS
li[data-level^="1"] {
/* some styles */
}
This seems to work just fine everywhere on page reload.
But when the data-attribute get set programmatically via JS, the CSS properties get rendered in all relevant desktop browsers, but not in mobile safari.
JS part looks like this:
this.$el.attr('data-level', this.model.getLevel())
Any ideas on how to force to apply those properties (refresh/repaint something) ?
I would like to avoid using the class attribute and different classes as things are more complex than shown here...
ok, changing data attributes simply doesn't seem to trigger a redraw of the element in all browsers !?
Changing the class attribute however does.
Kind of a workaround, but does the trick.
this.$el
.attr('data-level', this.model.getLevel())
.addClass('force-repaint')
.removeClass('force-repaint');
As seen here: Changing a data attribute in Safari, but the screen does not redraw to new CSS style
In my case, I was working with a font icon generated with icomoon and using the data attribute data-icon to change the HTML entity dynamically.
On page reload, it would work in tandem with this css:
[data-icon]:before {
content: attr(data-icon);
}
But without reload, and even by changing classes, it didn't change, just displayed the code.
<span class="font-icon" data-icon=""></span>
What worked for me was using this function, which I edited to the following (assuming code in the shape of e901):
export class StringUtils {
static emptyElement = document.createElement('div');
static fontCodeToSymbol(code: string): string {
let element = StringUtils.emptyElement;
let symbol: string | nullable = `&#x${code};`;
if (symbol && typeof symbol === 'string') {
element.innerHTML = symbol;
symbol = element.textContent;
element.textContent = '';
}
return symbol || '';
}
}
Which would directly feed the correct character in data-icon:
<span class="font-icon" data-icon=""></span>

How to dynamically set and modify CSS in JavaScript?

I have some JavaScript code that creates some div elements and it sets their CSS properties.
Because I would like to decouple CSS logic from my JavaScript code and because CSS is easier to read in its own .css file, I would like to set the CSS className of my element and then dynamically inject some values into the defined CSS property.
Here is what I would like to do :
style.css:
.myClass {
width: $insertedFromJS
}
script.js:
var myElement = document.createElement("div");
myElement.className = "myClass";
I want to do something like this but at that point myElement.style.width is empty
myElement.style.width.replaceAll("$insertedFromJS", "400px");
I think my problem here is that after the call to myElement.className = "myClass", the CSS is not yet applied.
If I understand your question properly, it sounds like you're trying to set placeholder text in your css file, and then use javascript to parse out the text with the css value you want to set for that class. You can't do that in the way you're trying to do it. In order to do that, you'd have to grab the content of the CSS file out of the dom, manipulate the text, and then save it back to the DOM. But that's a really overly-complicated way to go about doing something that...
myElement.style.width = "400px";
...can do for you in a couple of seconds. I know it doesn't really address the issue of decoupling css from js, but there's not really a whole lot you can do about that. You're trying to set css dynamically, after all.
Depending on what you're trying to accomplish, you might want to try defining multiple classes and just changing the className property in your js.
Setting the style, might be accomplished defining the inner-page style declaration.
Here is what i mean
var style = document.createElement('style');
style.type = 'text/css';
style.cssText = '.cssClass { color: #F00; }';
document.getElementsByTagName('head')[0].appendChild(style);
document.getElementById('someElementId').className = 'cssClass';
However the part of modifying it can be a lot of tricky than you think. Some regex solutions might do a good job. But here is another way, I found.
if (!document.styleSheets) return;
var csses = new Array();
if (document.styleSheets[0].cssRules) // Standards Compliant {
csses = document.styleSheets[0].cssRules;
}
else {
csses = document.styleSheets[0].rules; // IE
}
for (i=0;i<csses.length;i++) {
if ((csses[i].selectorText.toLowerCase()=='.cssClass') || (thecss[i].selectorText.toLowerCase()=='.borders'))
{
thecss[i].style.cssText="color:#000";
}
}
could you use jQuery on this? You could use
$(".class").css("property", val); /* or use the .width property */
There is a jQuery plugin called jQuery Rule,
http://flesler.blogspot.com/2007/11/jqueryrule.html
I tried it to dynamically set some div sizes of a board game. It works in FireFox, not in Chrome. I didn't try IE9.

changing css class model using JavaScript

Is it in any way possible, to change a css class model using JavaScript?
Pseudo code:
function updateClass(className, newData) {
cssInterface.alterClass(className, newData);
}
className being the name of the class, which is supposed to be changed (like ".footer") and newData being the new class content (like border: "1px solid pink;").
The target is, actually, just to save space: I am working with CSS3-animations, so changing one attribute of an element, which is affected by it's class, will terminate the animation of of it - The (in my case) font size won't change anymore. Using different classes will require an entire new set of classes for all affected elements, I'd like to avoid this.
I am not searching for a change via
element.className = "foo";
or
element.style.fontSize = "15pt";
Thanks for your help, guys :)
Here's my function to do this...
function changeCSS(typeAndClass, newRule, newValue) // modify the site CSS (if requred during scaling for smaller screen sizes)
{
var thisCSS=document.styleSheets[0] // get the CSS for the site as an array
var ruleSearch=thisCSS.cssRules? thisCSS.cssRules: thisCSS.rules // work out if the browser uses cssRules or not
for (i=0; i<ruleSearch.length; i++) // for every element in the CSS array
{
if(ruleSearch[i].selectorText==typeAndClass) // find the element that matches the type and class we are looking for
{
var target=ruleSearch[i] // create a variable to hold the specific CSS element
var typeExists = 1;
break; // and stop the loop
}
}
if (typeExists)
{
target.style[newRule] = newValue; // modify the desired class (typeAndClass) element (newRule) with its new value (newValue).
}
else
{
alert(typeAndClass + " does not exist.");
}
}
Called with (example)
changeCSS("div.headerfixed","-moz-transform-origin", "100% 0%");
hope this helps.
See my answer here. To answer your question: Yes, it's possible.
#CSS3: I tried exactly the same in one of my html5 experiments. I created an extra <style> element, and changed its contentText to the CSS class definitions I needed. Of course changing the cssRule object would be much cleaner :-)
As far as I can tell the CSS object model cannot easily tell you whether you already have an existing style rule for a particular class, but you can easily append a new rule for that class and it will override any previous declaration of that style.
I found an example of creating dynamic stylesheets.
You should take a look at dojo, it has some nice features where you can do just that..
require(["dojo/dom-class"], function(domClass){
// Add a class to some node:
domClass.add("someNode", "anewClass");
});
http://dojotoolkit.org/reference-guide/1.7/dojo/addClass.html

How to check if a css rule exists

I need to check if a CSS rule exists because I want to issue some warnings if a CSS file is not included.
What is the best way of doing this?
I could filter through window.document.styleSheets.cssRules, but I'm not sure how cross-browser this is (plus I notice on Stack Overflow that object is null for styleSheet[0]).
I would also like to keep dependencies to a minimum.
Is there a straightforward way to do this? Do I just have to create matching elements and test the effects?
Edit: If not, what are the cross-browser concerns of checking window.document.styleSheets?
I don't know if this is an option for you, but if it's a single file you want to check, then you can write your error message and toggle the style to hide it in that file.
<span class="include_error">Error: CSS was not included!</span>
CSS file:
.include_error {
display: none;
visibility: hidden;
}
I test for proper CSS installation using javascript.
I have a CSS rule in my stylesheet that sets a particular id to position: absolute.
#testObject {position: absolute;}
I then programmatically create a temporary div with visibility: hidden with that ID and get the computed style position. If it's not absolute, then the desired CSS is not installed.
If you can't put your own rule in the style sheet, then you can identify one or more rules that you think are representative of the stylesheet and not likely to change and design a temporary object that should get those rules and test for their existence that way.
Or, lastly, you could try to enumerate all the external style sheets and look for a particular filename that is included.
The point here is that if you want to see if an external style sheet is included, you have to pick something about that style sheet that you can look for (filename or some rule in it or some effect it causes).
Here is what I got that works. It's similar to the answers by #Smamatti and #jfriend00 but more fleshed out. I really wish there was a way to test for rules directly but oh well.
CSS:
.my-css-loaded-marker {
z-index: -98256; /*just a random number*/
}
JS:
$(function () { //Must run on jq ready or $('body') might not exist
var dummyElement = $('<p>')
.hide().css({height: 0, width: 0})
.addClass("my-css-loaded-marker")
.appendTo("body"); //Works without this on firefox for some reason
if (dummyElement.css("z-index") != -98256 && console && console.error) {
console.error("Could not find my-app.css styles. Application requires my-app.css to be loaded in order to function properly");
}
dummyElement.remove();
});
I would use a css selector like this from within your jquery widget.
$('link[href$="my-app.css"]')
If you get a result back it means there is a link element that has a href ending with "my-app.css"
Next use this function to validate a specific css property on an element you are depending on. I would suggest something specific to you styles like the width of a container rather something random like -9999 zindex
var getStyle = function(el, styleProp) {
var x = !!el.nodeType ? el : document.getElementById(el);
if (x.currentStyle)
var y = x.currentStyle[styleProp];
else if (window.getComputedStyle)
var y = document.defaultView.getComputedStyle(x, null).getPropertyValue(styleProp);
return y;
}
Like this
getStyle($('#stats-container')[0], "width")
or
getStyle("stats-container", "width")
If you are worried about not being able to edit other people's stylesheets, you can proxy them through a stylesheet of your own, using import
#import url('http://his-stylesheet.css');
.hideErrorMessage{ ... }
This is enough if you just want to know if your code is trying to load the stylesheet but won't help if you need to know if the foreign stylesheet was then loaded correctly.

How can I undo the setting of element.style properties?

I have an element in my document that has a background color and image set through a regular CSS rule.
When a certain event happens, I want to animate that item, highlighting it (I'm using Scriptaculous, but this question applies to any framework that'll do the same).
new Effect.Highlight(elHighlight, { startcolor: '#ffff99', endcolor: '#ffffff', afterFinish: fnEndOfFadeOut });
The problem i'm facing is that after the animation is done, the element is left with the following style (according to FireBug):
element.style {
background-color:transparent;
background-image:none;
}
Which overrides the CSS rule, since it's set at the element level, so I'm losing the background that the item used to have...
What I'm trying to do is, in the callback function I'm running after the animation is done, set the style properties to a value that'll make them "go away".
var fnEndOfFadeOut = function() {
elHighlight.style.backgroundColor = "xxxxx";
elHighlight.style.backgroundImage = "xxxxx";
}
What I'm trying to figure out is what to put in "xxxx" (or how to do the same thing in a different way).
I tried 'auto', 'inherit', and '' (blank string), and neither worked (I didn't really expect them to work, but I'm clueless here).
I also tried elHighlight.style = ""; which, expectably, threw an exception.
What can I do to overcome this?
I know I can put a span inside the element that I'm highlighting and highlight that span instead, but I'm hoping I'll be able to avoid the extra useless markup.
Chances are you're not setting the style on the correct element. It's probably being set somewhere up the line in a parent node.
elHighlight.style.backgroundColor = "";
elHighlight.style.backgroundImage = "";
You can also remove all the default styling by calling:
elHighlight.style.cssText = "";
In any case, you'll still have to do this on the specific element that is setting these properties, which means you may need to do a recursion on parentNode until you find it.
Try
elHighlight.style.removeProperty('background-color')
elHighlight.style.removeProperty('background-image')
have you tried elHightlight.style.background = "";?
I have a highlighter code on my site and this works
function highlight(id) {
var elements = getElementsByClass("softwareItem");
for (var ix in elements){
elements[ix].style.background = ""; //This clears any previous highlight
}
document.getElementById(id).style.background = "#E7F3FA";
}
An HTML element can have multiple CSS classes. Put your highlight information inside a CSS class. Add this class to your element to highlight it. Remove the class to undo the effect.

Categories

Resources