Set css attribute in javascript - javascript

This is my function set css attributes like as jquery
that.getNode = function() {
return element; // element is HTML node
};
that.css = function(obj) {
var node = that.getNode(),
attr;
if (node && node.style) {
for (attr in obj) {
if (obj.hasOwnProperty(attr) && node.style.hasOwnProperty(attr)) {
node.style[attr] = obj[attr];
}
}
}
return that;
};
Then I call, it runs on Chrome normally but can't work on IE9 or firefox
that.css({
border: "1px solid black"
});

Seems that the following returns false in some browsers:
node.style.hasOwnProperty(attr)
In these cases, the properties are being inherited from a prototype rather than owned by the Object (node.style) itself.
If you want to test that the property exists, whether owned or inherited, you can try the in operator:
attr in node.style
In context:
that.css = function(obj) {
var node = that.getNode(),
attr;
if (node && node.style) {
for (attr in obj) {
if (obj.hasOwnProperty(attr) && attr in node.style) {
node.style[attr] = obj[attr];
}
}
}
return that;
};

Make a Cross-browser solution by hand is lot of work, I recommend using some JavaScript Framework like JQuery, it will do the hard work for you.
If you choose JQuery you have a function named .CSS and you could do this task in 1 line, for example:
You have an HTML element:
<div id="someID"> Content </div>
right? so you want to add some CSS Classes to this DIV, you only need to say to JQuery which node in the HTML DOM want to select and with the function .CSS you can set some CSS Attributes (and other things):
$("#someID").css("SOME-ATTRIbute","SOME-VALUE");
(#someID is the ID of the element, .CSS is the function)
easy eh?, Use JQuery or any other Javascript Frameworks that will help you to do a cross-browser application.
PS: sorry for my english

Related

Set HTML stylesheet from JavaScript [duplicate]

Is it possible to make changes to a CSS rule-set dynamically (i.e. some JS which would change a CSS rule-set when the user clicks a widget)
This particular CSS rule-set is applied to lots of elements (via a class selector) on the page and I want to modify it when the user clicks the widget, so that all the elements having the class change.
You can, but it's rather cumbersome. The best reference on how to do it is the following article: Totally Pwn CSS with Javascript (web archive link).
I managed to get it to work with Firefox and IE - I couldn't in Chrome, though it appears that it supports the DOM methods.ricosrealm reports that it works in Chrome, too.
This is a modern version based on Totally Pwn CSS with Javascript. It's ES6 I hope don't mind.
function getCSSRule(ruleName) {
ruleName = ruleName.toLowerCase();
var result = null;
var find = Array.prototype.find;
find.call(document.styleSheets, styleSheet => {
result = find.call(styleSheet.cssRules, cssRule => {
return cssRule instanceof CSSStyleRule
&& cssRule.selectorText.toLowerCase() == ruleName;
});
return result != null;
});
return result;
}
This function returns a CSSStyleRule that you can use like this:
var header = getCSSRule('#header');
header.style.backgroundColor = 'red';
Also document.styleSheets list references of the CSSStylesSheets Objects. Other way to acces a specific sytleSheet in the page is by assigning an id to the style or link element in the html code, and get it in javascript using document.getElementById('my-style').sheet. This are some useful methods:
Major Browsers and IE9+ : insertRule(), deleteRule(), removeProperty().
Major Browsers, Firefox? and IE9+ : setProperty().
<stye id="my-style" ...
....
var myStyle = document.getElementById('my-style').sheet
myStyle.insertRule('#header { background: red; }', 0);
It is also possible to dynamically create a new style element to store dynamic created styles, I think should be way to avoid conflicts.
You can edit CLASS in document styleshets as follows
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
function edit() {
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
}
.box {
margin: 10px;
padding: 10px;
background: yellow;
}
<button onclick="edit()" >Click me</button>
<div class="box" >My box 1</div>
<div class="box" >My box 2</div>
<div class="box" >My box 3</div>
I tried the code via link from #alex-gyoshev comment, but it dosn't work
it fails on the CSS rules with Google fonts in Chrome
it fails on FireFox security checks
So I changed it slightly, but deleted delete functionality since it wasn't needed for me. Checked in IE 11, FireFox 32, Chrome 37 and Opera 26.
function getCSSRule(ruleName) { // Return requested style object
ruleName = ruleName.toLowerCase(); // Convert test string to lower case.
var styleSheet;
var i, ii;
var cssRule = false; // Initialize cssRule.
var cssRules;
if (document.styleSheets) { // If browser can play with stylesheets
for (i = 0; i < document.styleSheets.length; i++) { // For each stylesheet
styleSheet = document.styleSheets[i];
if (!styleSheet.href) {
if (styleSheet.cssRules) { // Browser uses cssRules?
cssRules = styleSheet.cssRules; // Yes --Mozilla Style
} else { // Browser usses rules?
cssRules = styleSheet.rules; // Yes IE style.
} // End IE check.
if (cssRules) {
for (ii = 0; ii < cssRules.length; ii++) {
cssRule = cssRules[ii];
if (cssRule) { // If we found a rule...
// console.log(cssRule);
if (cssRule.selectorText) {
console.log(cssRule.selectorText);
if (cssRule.selectorText.toLowerCase() == ruleName) { // match ruleName?
return cssRule; // return the style object.
}
}
}
}
}
}
}
}
return false; // we found NOTHING!
}
Depending on what you're trying to achieve, a better solution might be to change/add a class to a containing element (body would do!), and define classes accordingly.
.yourclass { color: black }
#wrapper.foo .yourclass { color: red }
#wrapper.bar .yourclass { color: blue }
then you can just use
document.getElementById('wrapper').className='foo';
(or your chosen js framework's wrapper for the same) to change everything with class yourclass inside whatever your wrapper element is.
The APIs for editing stylesheets with JS are, sadly, not consistent across browsers. The YUI Stylesheet Utility attempts to smooth over these differences so you could just use that. You could also look at the source code to figure out how it works if you don't want to use YUI itself.
give your style tag an id, like <style id="ssID">
if someonelse is making your styles for you
tell THAT person to give the style tag an id -
that way you can access it directly without
scrambling around wondering what its index is
// create a hash table
var cssHash = {};
// loop through and populate the hash table
for (let i in (r = ss0.sheet.rules)) {
// selectorText is the name of the rule - set the value equal to the rule
cssHash[r[i].selectorText] = r[i];
}
now you have a hash table for everything in the style sheet -
note that some values will be undefined, but not for
any of the things you care about
if you have, for instance, a class called #menuItem
and you want to change its color to black, do this
cssHash['#menuItem'].style.color = #000;
that line will set the color of the style of the rule
whose index was looked up in the hash table (cssHash)
by the name '#menuItem'
more importantly, you probably have several different
classes that you want to change all at once
kind of like when you switched majors in college
let's say you have four different classes
and you want to set all of their background colors
to the same value, that some user selected from an input
the color selector tag is <input id="bColor" type="color">
and the class rules you want to change are called
#menuItem .homeAddr span and #vacuum:hover
// create a listener for that color selector
bColor.addEventListener('input', function (e) {
// loop through a split list of the four class names
'#menuItem .homeAddr span #vacuum:hover'.split(' ').forEach(function (obj) {
// use the hash table to look up the index of each name
// and set the background color equal to the color input's value
cssHash[obj].style.backgroundColor = bColor.value;
});
}, false); // false added here for the sake of non-brevity
While setAttribute is nice, there is a standard way of doing this across most browsers:
htmlElement.className = 'someClass';
To do it over many elements, you will need a cross browser solution:
function getElementsByClassName( className, context, tagName ) {
context = context || document;
if ( typeof context.getElementsByClassName === 'function' )
return context.getElementsByClassName( className );
if ( typeof context.getElementsByTagName !== 'function' )
return [];
var elements = typeof tagName === 'string' ? context.getElementsByTagName( tagName ) :
context.getElementsByTagName('*'),
ret = [];
for ( var i = 0, il = elements.length; i < il; i++ )
if ( elements[ i ].className.match( className ) )
ret.push( elements[ i ] );
return ret;
}
var elements = getElementsByClassName('someClass');
for ( var i = 0, il = elements.length; i < il; i++ )
elements[ i ].className = 'newClass';
You may want to replace the line:
if ( elements[ i ].className.match( className ) )
With some Regular Expression, but you will have to escape special characters in that case.
To check all stylesheets for the rule and set it:
Your rule:
.aaa: {
background-color: green
}
[...document.styleSheets].flatMap(s=>[...s.cssRules])
.find(i=>i.selectorText=='.aaa').style.backgroundColor = 'red';
Note that the css styles, when accessed through javascript, do not have dashes in them. In the example above, background-color becomes backgroundColor

Altering Stylesheet with javascript? [duplicate]

Is it possible to make changes to a CSS rule-set dynamically (i.e. some JS which would change a CSS rule-set when the user clicks a widget)
This particular CSS rule-set is applied to lots of elements (via a class selector) on the page and I want to modify it when the user clicks the widget, so that all the elements having the class change.
You can, but it's rather cumbersome. The best reference on how to do it is the following article: Totally Pwn CSS with Javascript (web archive link).
I managed to get it to work with Firefox and IE - I couldn't in Chrome, though it appears that it supports the DOM methods.ricosrealm reports that it works in Chrome, too.
This is a modern version based on Totally Pwn CSS with Javascript. It's ES6 I hope don't mind.
function getCSSRule(ruleName) {
ruleName = ruleName.toLowerCase();
var result = null;
var find = Array.prototype.find;
find.call(document.styleSheets, styleSheet => {
result = find.call(styleSheet.cssRules, cssRule => {
return cssRule instanceof CSSStyleRule
&& cssRule.selectorText.toLowerCase() == ruleName;
});
return result != null;
});
return result;
}
This function returns a CSSStyleRule that you can use like this:
var header = getCSSRule('#header');
header.style.backgroundColor = 'red';
Also document.styleSheets list references of the CSSStylesSheets Objects. Other way to acces a specific sytleSheet in the page is by assigning an id to the style or link element in the html code, and get it in javascript using document.getElementById('my-style').sheet. This are some useful methods:
Major Browsers and IE9+ : insertRule(), deleteRule(), removeProperty().
Major Browsers, Firefox? and IE9+ : setProperty().
<stye id="my-style" ...
....
var myStyle = document.getElementById('my-style').sheet
myStyle.insertRule('#header { background: red; }', 0);
It is also possible to dynamically create a new style element to store dynamic created styles, I think should be way to avoid conflicts.
You can edit CLASS in document styleshets as follows
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
function edit() {
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
}
.box {
margin: 10px;
padding: 10px;
background: yellow;
}
<button onclick="edit()" >Click me</button>
<div class="box" >My box 1</div>
<div class="box" >My box 2</div>
<div class="box" >My box 3</div>
I tried the code via link from #alex-gyoshev comment, but it dosn't work
it fails on the CSS rules with Google fonts in Chrome
it fails on FireFox security checks
So I changed it slightly, but deleted delete functionality since it wasn't needed for me. Checked in IE 11, FireFox 32, Chrome 37 and Opera 26.
function getCSSRule(ruleName) { // Return requested style object
ruleName = ruleName.toLowerCase(); // Convert test string to lower case.
var styleSheet;
var i, ii;
var cssRule = false; // Initialize cssRule.
var cssRules;
if (document.styleSheets) { // If browser can play with stylesheets
for (i = 0; i < document.styleSheets.length; i++) { // For each stylesheet
styleSheet = document.styleSheets[i];
if (!styleSheet.href) {
if (styleSheet.cssRules) { // Browser uses cssRules?
cssRules = styleSheet.cssRules; // Yes --Mozilla Style
} else { // Browser usses rules?
cssRules = styleSheet.rules; // Yes IE style.
} // End IE check.
if (cssRules) {
for (ii = 0; ii < cssRules.length; ii++) {
cssRule = cssRules[ii];
if (cssRule) { // If we found a rule...
// console.log(cssRule);
if (cssRule.selectorText) {
console.log(cssRule.selectorText);
if (cssRule.selectorText.toLowerCase() == ruleName) { // match ruleName?
return cssRule; // return the style object.
}
}
}
}
}
}
}
}
return false; // we found NOTHING!
}
Depending on what you're trying to achieve, a better solution might be to change/add a class to a containing element (body would do!), and define classes accordingly.
.yourclass { color: black }
#wrapper.foo .yourclass { color: red }
#wrapper.bar .yourclass { color: blue }
then you can just use
document.getElementById('wrapper').className='foo';
(or your chosen js framework's wrapper for the same) to change everything with class yourclass inside whatever your wrapper element is.
The APIs for editing stylesheets with JS are, sadly, not consistent across browsers. The YUI Stylesheet Utility attempts to smooth over these differences so you could just use that. You could also look at the source code to figure out how it works if you don't want to use YUI itself.
give your style tag an id, like <style id="ssID">
if someonelse is making your styles for you
tell THAT person to give the style tag an id -
that way you can access it directly without
scrambling around wondering what its index is
// create a hash table
var cssHash = {};
// loop through and populate the hash table
for (let i in (r = ss0.sheet.rules)) {
// selectorText is the name of the rule - set the value equal to the rule
cssHash[r[i].selectorText] = r[i];
}
now you have a hash table for everything in the style sheet -
note that some values will be undefined, but not for
any of the things you care about
if you have, for instance, a class called #menuItem
and you want to change its color to black, do this
cssHash['#menuItem'].style.color = #000;
that line will set the color of the style of the rule
whose index was looked up in the hash table (cssHash)
by the name '#menuItem'
more importantly, you probably have several different
classes that you want to change all at once
kind of like when you switched majors in college
let's say you have four different classes
and you want to set all of their background colors
to the same value, that some user selected from an input
the color selector tag is <input id="bColor" type="color">
and the class rules you want to change are called
#menuItem .homeAddr span and #vacuum:hover
// create a listener for that color selector
bColor.addEventListener('input', function (e) {
// loop through a split list of the four class names
'#menuItem .homeAddr span #vacuum:hover'.split(' ').forEach(function (obj) {
// use the hash table to look up the index of each name
// and set the background color equal to the color input's value
cssHash[obj].style.backgroundColor = bColor.value;
});
}, false); // false added here for the sake of non-brevity
While setAttribute is nice, there is a standard way of doing this across most browsers:
htmlElement.className = 'someClass';
To do it over many elements, you will need a cross browser solution:
function getElementsByClassName( className, context, tagName ) {
context = context || document;
if ( typeof context.getElementsByClassName === 'function' )
return context.getElementsByClassName( className );
if ( typeof context.getElementsByTagName !== 'function' )
return [];
var elements = typeof tagName === 'string' ? context.getElementsByTagName( tagName ) :
context.getElementsByTagName('*'),
ret = [];
for ( var i = 0, il = elements.length; i < il; i++ )
if ( elements[ i ].className.match( className ) )
ret.push( elements[ i ] );
return ret;
}
var elements = getElementsByClassName('someClass');
for ( var i = 0, il = elements.length; i < il; i++ )
elements[ i ].className = 'newClass';
You may want to replace the line:
if ( elements[ i ].className.match( className ) )
With some Regular Expression, but you will have to escape special characters in that case.
To check all stylesheets for the rule and set it:
Your rule:
.aaa: {
background-color: green
}
[...document.styleSheets].flatMap(s=>[...s.cssRules])
.find(i=>i.selectorText=='.aaa').style.backgroundColor = 'red';
Note that the css styles, when accessed through javascript, do not have dashes in them. In the example above, background-color becomes backgroundColor

Editing css styles with jquery [duplicate]

Is it possible to make changes to a CSS rule-set dynamically (i.e. some JS which would change a CSS rule-set when the user clicks a widget)
This particular CSS rule-set is applied to lots of elements (via a class selector) on the page and I want to modify it when the user clicks the widget, so that all the elements having the class change.
You can, but it's rather cumbersome. The best reference on how to do it is the following article: Totally Pwn CSS with Javascript (web archive link).
I managed to get it to work with Firefox and IE - I couldn't in Chrome, though it appears that it supports the DOM methods.ricosrealm reports that it works in Chrome, too.
This is a modern version based on Totally Pwn CSS with Javascript. It's ES6 I hope don't mind.
function getCSSRule(ruleName) {
ruleName = ruleName.toLowerCase();
var result = null;
var find = Array.prototype.find;
find.call(document.styleSheets, styleSheet => {
result = find.call(styleSheet.cssRules, cssRule => {
return cssRule instanceof CSSStyleRule
&& cssRule.selectorText.toLowerCase() == ruleName;
});
return result != null;
});
return result;
}
This function returns a CSSStyleRule that you can use like this:
var header = getCSSRule('#header');
header.style.backgroundColor = 'red';
Also document.styleSheets list references of the CSSStylesSheets Objects. Other way to acces a specific sytleSheet in the page is by assigning an id to the style or link element in the html code, and get it in javascript using document.getElementById('my-style').sheet. This are some useful methods:
Major Browsers and IE9+ : insertRule(), deleteRule(), removeProperty().
Major Browsers, Firefox? and IE9+ : setProperty().
<stye id="my-style" ...
....
var myStyle = document.getElementById('my-style').sheet
myStyle.insertRule('#header { background: red; }', 0);
It is also possible to dynamically create a new style element to store dynamic created styles, I think should be way to avoid conflicts.
You can edit CLASS in document styleshets as follows
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
function edit() {
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
}
.box {
margin: 10px;
padding: 10px;
background: yellow;
}
<button onclick="edit()" >Click me</button>
<div class="box" >My box 1</div>
<div class="box" >My box 2</div>
<div class="box" >My box 3</div>
I tried the code via link from #alex-gyoshev comment, but it dosn't work
it fails on the CSS rules with Google fonts in Chrome
it fails on FireFox security checks
So I changed it slightly, but deleted delete functionality since it wasn't needed for me. Checked in IE 11, FireFox 32, Chrome 37 and Opera 26.
function getCSSRule(ruleName) { // Return requested style object
ruleName = ruleName.toLowerCase(); // Convert test string to lower case.
var styleSheet;
var i, ii;
var cssRule = false; // Initialize cssRule.
var cssRules;
if (document.styleSheets) { // If browser can play with stylesheets
for (i = 0; i < document.styleSheets.length; i++) { // For each stylesheet
styleSheet = document.styleSheets[i];
if (!styleSheet.href) {
if (styleSheet.cssRules) { // Browser uses cssRules?
cssRules = styleSheet.cssRules; // Yes --Mozilla Style
} else { // Browser usses rules?
cssRules = styleSheet.rules; // Yes IE style.
} // End IE check.
if (cssRules) {
for (ii = 0; ii < cssRules.length; ii++) {
cssRule = cssRules[ii];
if (cssRule) { // If we found a rule...
// console.log(cssRule);
if (cssRule.selectorText) {
console.log(cssRule.selectorText);
if (cssRule.selectorText.toLowerCase() == ruleName) { // match ruleName?
return cssRule; // return the style object.
}
}
}
}
}
}
}
}
return false; // we found NOTHING!
}
Depending on what you're trying to achieve, a better solution might be to change/add a class to a containing element (body would do!), and define classes accordingly.
.yourclass { color: black }
#wrapper.foo .yourclass { color: red }
#wrapper.bar .yourclass { color: blue }
then you can just use
document.getElementById('wrapper').className='foo';
(or your chosen js framework's wrapper for the same) to change everything with class yourclass inside whatever your wrapper element is.
The APIs for editing stylesheets with JS are, sadly, not consistent across browsers. The YUI Stylesheet Utility attempts to smooth over these differences so you could just use that. You could also look at the source code to figure out how it works if you don't want to use YUI itself.
give your style tag an id, like <style id="ssID">
if someonelse is making your styles for you
tell THAT person to give the style tag an id -
that way you can access it directly without
scrambling around wondering what its index is
// create a hash table
var cssHash = {};
// loop through and populate the hash table
for (let i in (r = ss0.sheet.rules)) {
// selectorText is the name of the rule - set the value equal to the rule
cssHash[r[i].selectorText] = r[i];
}
now you have a hash table for everything in the style sheet -
note that some values will be undefined, but not for
any of the things you care about
if you have, for instance, a class called #menuItem
and you want to change its color to black, do this
cssHash['#menuItem'].style.color = #000;
that line will set the color of the style of the rule
whose index was looked up in the hash table (cssHash)
by the name '#menuItem'
more importantly, you probably have several different
classes that you want to change all at once
kind of like when you switched majors in college
let's say you have four different classes
and you want to set all of their background colors
to the same value, that some user selected from an input
the color selector tag is <input id="bColor" type="color">
and the class rules you want to change are called
#menuItem .homeAddr span and #vacuum:hover
// create a listener for that color selector
bColor.addEventListener('input', function (e) {
// loop through a split list of the four class names
'#menuItem .homeAddr span #vacuum:hover'.split(' ').forEach(function (obj) {
// use the hash table to look up the index of each name
// and set the background color equal to the color input's value
cssHash[obj].style.backgroundColor = bColor.value;
});
}, false); // false added here for the sake of non-brevity
While setAttribute is nice, there is a standard way of doing this across most browsers:
htmlElement.className = 'someClass';
To do it over many elements, you will need a cross browser solution:
function getElementsByClassName( className, context, tagName ) {
context = context || document;
if ( typeof context.getElementsByClassName === 'function' )
return context.getElementsByClassName( className );
if ( typeof context.getElementsByTagName !== 'function' )
return [];
var elements = typeof tagName === 'string' ? context.getElementsByTagName( tagName ) :
context.getElementsByTagName('*'),
ret = [];
for ( var i = 0, il = elements.length; i < il; i++ )
if ( elements[ i ].className.match( className ) )
ret.push( elements[ i ] );
return ret;
}
var elements = getElementsByClassName('someClass');
for ( var i = 0, il = elements.length; i < il; i++ )
elements[ i ].className = 'newClass';
You may want to replace the line:
if ( elements[ i ].className.match( className ) )
With some Regular Expression, but you will have to escape special characters in that case.
To check all stylesheets for the rule and set it:
Your rule:
.aaa: {
background-color: green
}
[...document.styleSheets].flatMap(s=>[...s.cssRules])
.find(i=>i.selectorText=='.aaa').style.backgroundColor = 'red';
Note that the css styles, when accessed through javascript, do not have dashes in them. In the example above, background-color becomes backgroundColor

jQuery Selector + SVG Incompatible?

I've been working with an HTML5 document with inline SVG and javascript animation.
I'd like to have a box pop up when the user clicks anywhere, and I'd like the box to go away when the user clicks somewhere that isn't the box. This means I can't use $(window).click(), which works.
I've tried selecting the SVGs on top by giving them class names and using $(".svgclassname").click(), but this doesn't seem to work. Neither does selecting individual ones with $("#svgname").click().
What is the problem?
(When I replace $(".eyesvg") with $(window), a blue box appears near the cursor when the user clicks anywhere in the window.)
This happens because SVG DOM spec differs a lot from HTML DOM.
SVG DOM is a different dialect, and some properties have same names but mean different things. For example, to get the className of an svg element, you use:
svg.className.baseVal
The properites affected by this are
className is SVGAnimatedString
height,width, x, y, offsetWidth, offsetHeight are SVGAnimatedLength
These Animated properties are structs, with baseVal holding the same value you'd find in HTML DOM and animatedVal holding I am not sure what.
SVG DOM is also missing some properties libraries depend on, such as innerHTML.
This breaks jQuery in many ways, anything that depends on above properties fails.
In general, SVG DOM and HTML DOM do not mix very well. They work together just enough to lure you in, and then things break quietly, and another angel loses its wings.
I wrote a little jQuery extension that wraps SVG elements to make them look more like HTML DOM
(function (jQuery){
function svgWrapper(el) {
this._svgEl = el;
this.__proto__ = el;
Object.defineProperty(this, "className", {
get: function(){ return this._svgEl.className.baseVal; },
set: function(value){ this._svgEl.className.baseVal = value; }
});
Object.defineProperty(this, "width", {
get: function(){ return this._svgEl.width.baseVal.value; },
set: function(value){ this._svgEl.width.baseVal.value = value; }
});
Object.defineProperty(this, "height", {
get: function(){ return this._svgEl.height.baseVal.value; },
set: function(value){ this._svgEl.height.baseVal.value = value; }
});
Object.defineProperty(this, "x", {
get: function(){ return this._svgEl.x.baseVal.value; },
set: function(value){ this._svgEl.x.baseVal.value = value; }
});
Object.defineProperty(this, "y", {
get: function(){ return this._svgEl.y.baseVal.value; },
set: function(value){ this._svgEl.y.baseVal.value = value; }
});
Object.defineProperty(this, "offsetWidth", {
get: function(){ return this._svgEl.width.baseVal.value; },
set: function(value){ this._svgEl.width.baseVal.value = value; }
});
Object.defineProperty(this, "offsetHeight", {
get: function(){ return this._svgEl.height.baseVal.value; },
set: function(value){ this._svgEl.height.baseVal.value = value; }
});
};
jQuery.fn.wrapSvg = function() {
return this.map(function(i, el) {
if (el.namespaceURI == "http://www.w3.org/2000/svg" && !('_svgEl' in el))
return new svgWrapper(el);
else
return el;
});
};
})(window.jQuery);
It creates a wrapper around SVG objects that makes them look like HTML DOM to jQuery. I've used it with jQuery-UI to make my SVG elements droppable.
The lack of DOM interoperability between HTML and SVG is a total disaster. All the sweet utility libraries written for HTML have to be reinvented for SVG.
u can use jquery-svg plugin, like a charm:
<script>
//get svg object, like a jquery object
var svg = $("#cars").getSVG();
//use jquery functions to do some thing
svg.find("g path:first-child()").attr('fill', color);
</script>
sometimes I don't get it... but actually it doesn't work with the class-selector. If you use the id $("#mysvg") or the element $("svg") it does work! Strange....
And it only works when you move the onClick script from the header to the body after the svg element! jquery can only bind the onclick when the element is declared before the binding.
You have to use CSS-path from div to SVG element to click on the object
as per below example:
$('div#layout > svg > #line').click()

Changing a CSS rule-set from Javascript

Is it possible to make changes to a CSS rule-set dynamically (i.e. some JS which would change a CSS rule-set when the user clicks a widget)
This particular CSS rule-set is applied to lots of elements (via a class selector) on the page and I want to modify it when the user clicks the widget, so that all the elements having the class change.
You can, but it's rather cumbersome. The best reference on how to do it is the following article: Totally Pwn CSS with Javascript (web archive link).
I managed to get it to work with Firefox and IE - I couldn't in Chrome, though it appears that it supports the DOM methods.ricosrealm reports that it works in Chrome, too.
This is a modern version based on Totally Pwn CSS with Javascript. It's ES6 I hope don't mind.
function getCSSRule(ruleName) {
ruleName = ruleName.toLowerCase();
var result = null;
var find = Array.prototype.find;
find.call(document.styleSheets, styleSheet => {
result = find.call(styleSheet.cssRules, cssRule => {
return cssRule instanceof CSSStyleRule
&& cssRule.selectorText.toLowerCase() == ruleName;
});
return result != null;
});
return result;
}
This function returns a CSSStyleRule that you can use like this:
var header = getCSSRule('#header');
header.style.backgroundColor = 'red';
Also document.styleSheets list references of the CSSStylesSheets Objects. Other way to acces a specific sytleSheet in the page is by assigning an id to the style or link element in the html code, and get it in javascript using document.getElementById('my-style').sheet. This are some useful methods:
Major Browsers and IE9+ : insertRule(), deleteRule(), removeProperty().
Major Browsers, Firefox? and IE9+ : setProperty().
<stye id="my-style" ...
....
var myStyle = document.getElementById('my-style').sheet
myStyle.insertRule('#header { background: red; }', 0);
It is also possible to dynamically create a new style element to store dynamic created styles, I think should be way to avoid conflicts.
You can edit CLASS in document styleshets as follows
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
function edit() {
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
}
.box {
margin: 10px;
padding: 10px;
background: yellow;
}
<button onclick="edit()" >Click me</button>
<div class="box" >My box 1</div>
<div class="box" >My box 2</div>
<div class="box" >My box 3</div>
I tried the code via link from #alex-gyoshev comment, but it dosn't work
it fails on the CSS rules with Google fonts in Chrome
it fails on FireFox security checks
So I changed it slightly, but deleted delete functionality since it wasn't needed for me. Checked in IE 11, FireFox 32, Chrome 37 and Opera 26.
function getCSSRule(ruleName) { // Return requested style object
ruleName = ruleName.toLowerCase(); // Convert test string to lower case.
var styleSheet;
var i, ii;
var cssRule = false; // Initialize cssRule.
var cssRules;
if (document.styleSheets) { // If browser can play with stylesheets
for (i = 0; i < document.styleSheets.length; i++) { // For each stylesheet
styleSheet = document.styleSheets[i];
if (!styleSheet.href) {
if (styleSheet.cssRules) { // Browser uses cssRules?
cssRules = styleSheet.cssRules; // Yes --Mozilla Style
} else { // Browser usses rules?
cssRules = styleSheet.rules; // Yes IE style.
} // End IE check.
if (cssRules) {
for (ii = 0; ii < cssRules.length; ii++) {
cssRule = cssRules[ii];
if (cssRule) { // If we found a rule...
// console.log(cssRule);
if (cssRule.selectorText) {
console.log(cssRule.selectorText);
if (cssRule.selectorText.toLowerCase() == ruleName) { // match ruleName?
return cssRule; // return the style object.
}
}
}
}
}
}
}
}
return false; // we found NOTHING!
}
Depending on what you're trying to achieve, a better solution might be to change/add a class to a containing element (body would do!), and define classes accordingly.
.yourclass { color: black }
#wrapper.foo .yourclass { color: red }
#wrapper.bar .yourclass { color: blue }
then you can just use
document.getElementById('wrapper').className='foo';
(or your chosen js framework's wrapper for the same) to change everything with class yourclass inside whatever your wrapper element is.
The APIs for editing stylesheets with JS are, sadly, not consistent across browsers. The YUI Stylesheet Utility attempts to smooth over these differences so you could just use that. You could also look at the source code to figure out how it works if you don't want to use YUI itself.
give your style tag an id, like <style id="ssID">
if someonelse is making your styles for you
tell THAT person to give the style tag an id -
that way you can access it directly without
scrambling around wondering what its index is
// create a hash table
var cssHash = {};
// loop through and populate the hash table
for (let i in (r = ss0.sheet.rules)) {
// selectorText is the name of the rule - set the value equal to the rule
cssHash[r[i].selectorText] = r[i];
}
now you have a hash table for everything in the style sheet -
note that some values will be undefined, but not for
any of the things you care about
if you have, for instance, a class called #menuItem
and you want to change its color to black, do this
cssHash['#menuItem'].style.color = #000;
that line will set the color of the style of the rule
whose index was looked up in the hash table (cssHash)
by the name '#menuItem'
more importantly, you probably have several different
classes that you want to change all at once
kind of like when you switched majors in college
let's say you have four different classes
and you want to set all of their background colors
to the same value, that some user selected from an input
the color selector tag is <input id="bColor" type="color">
and the class rules you want to change are called
#menuItem .homeAddr span and #vacuum:hover
// create a listener for that color selector
bColor.addEventListener('input', function (e) {
// loop through a split list of the four class names
'#menuItem .homeAddr span #vacuum:hover'.split(' ').forEach(function (obj) {
// use the hash table to look up the index of each name
// and set the background color equal to the color input's value
cssHash[obj].style.backgroundColor = bColor.value;
});
}, false); // false added here for the sake of non-brevity
While setAttribute is nice, there is a standard way of doing this across most browsers:
htmlElement.className = 'someClass';
To do it over many elements, you will need a cross browser solution:
function getElementsByClassName( className, context, tagName ) {
context = context || document;
if ( typeof context.getElementsByClassName === 'function' )
return context.getElementsByClassName( className );
if ( typeof context.getElementsByTagName !== 'function' )
return [];
var elements = typeof tagName === 'string' ? context.getElementsByTagName( tagName ) :
context.getElementsByTagName('*'),
ret = [];
for ( var i = 0, il = elements.length; i < il; i++ )
if ( elements[ i ].className.match( className ) )
ret.push( elements[ i ] );
return ret;
}
var elements = getElementsByClassName('someClass');
for ( var i = 0, il = elements.length; i < il; i++ )
elements[ i ].className = 'newClass';
You may want to replace the line:
if ( elements[ i ].className.match( className ) )
With some Regular Expression, but you will have to escape special characters in that case.
To check all stylesheets for the rule and set it:
Your rule:
.aaa: {
background-color: green
}
[...document.styleSheets].flatMap(s=>[...s.cssRules])
.find(i=>i.selectorText=='.aaa').style.backgroundColor = 'red';
Note that the css styles, when accessed through javascript, do not have dashes in them. In the example above, background-color becomes backgroundColor

Categories